c# - sistemas - sistema de recomendacion tesis
Necesito ayuda para obtener la frecuencia de la CPU (3)
Sí, ese código se encuentra y ocupado, espera durante un segundo completo, lo que hace que ese núcleo esté 100% ocupado por un segundo. Un segundo es tiempo más que suficiente para que los algoritmos de sincronización dinámica detecten la carga y apaguen la frecuencia de la CPU fuera de los estados de ahorro de energía. No me sorprendería si los procesadores con boost en realidad muestran una frecuencia superior a la frecuencia etiquetada.
El concepto no está mal, sin embargo. Lo que tienes que hacer es dormir durante un intervalo de aproximadamente un segundo. Luego, en lugar de suponer que las invocaciones de RDTSC estaban separadas exactamente un segundo, divida por el tiempo real indicado por QueryPerformanceCounter
.
Además, recomiendo verificar RDTSC
antes y después de la llamada QueryPerformanceCounter
, para detectar si hubo un cambio de contexto entre RDTSC
y QueryPerformanceCounter
que podría arruinar los resultados.
Desafortunadamente, RDTSC
en nuevos procesadores en realidad no cuenta los ciclos de reloj de la CPU. Por lo tanto, esto no refleja la velocidad del reloj de la CPU que cambia dinámicamente (sí mide la tasa nominal sin la espera ocupada, por lo que es una gran mejora con respecto al código provisto en la pregunta).
Entonces, parece que necesitarás acceder a los registros específicos del modelo después de todo. Lo cual no se puede hacer desde el modo de usuario . El proyecto OpenHardwareMonitor tiene un controlador que se puede usar y un código para los cálculos de frecuencia
float ProcSpeedCalc()
{
/*
RdTSC:
It''s the Pentium instruction "ReaD Time Stamp Counter". It measures the
number of clock cycles that have passed since the processor was reset, as a
64-bit number. That''s what the <CODE>_emit</CODE> lines do.
*/
// Microsoft inline assembler knows the rdtsc instruction. No need for emit.
// variables for the CPU cycle counter (unknown rate):
__int64 tscBefore, tscAfter, tscCheck;
// variables for the Performance Counter 9steady known rate):
LARGE_INTEGER hpetFreq, hpetBefore, hpetAfter;
// retrieve performance-counter frequency per second:
if (!QueryPerformanceFrequency(&hpetFreq)) return 0;
int retryLimit = 10;
do {
// read CPU cycle count
_asm
{
rdtsc
mov DWORD PTR tscBefore, eax
mov DWORD PTR [tscBefore + 4], edx
}
// retrieve the current value of the performance counter:
QueryPerformanceCounter(&hpetBefore);
// read CPU cycle count again, to detect context switch
_asm
{
rdtsc
mov DWORD PTR tscCheck, eax
mov DWORD PTR [tscCheck + 4], edx
}
} while ((tscCheck - tscBefore) > 800 && (--retryLimit) > 0);
Sleep(1000);
do {
// read CPU cycle count
_asm
{
rdtsc
mov DWORD PTR tscAfter, eax
mov DWORD PTR [tscAfter + 4], edx
}
// retrieve the current value of the performance counter:
QueryPerformanceCounter(&hpetAfter);
// read CPU cycle count again, to detect context switch
_asm
{
rdtsc
mov DWORD PTR tscCheck, eax
mov DWORD PTR [tscCheck + 4], edx
}
} while ((tscCheck - tscAfter) > 800 && (--retryLimit) > 0);
// stop-start is speed in Hz divided by 1,000,000 is speed in MHz
return (double)(tscAfter - tscBefore) / (double)(hpetAfter.QuadPart - hpetBefore.QuadPart) * (double)hpetFreq.QuadPart / 1.0e6;
}
La mayoría de los compiladores proporcionan un __rdtsc()
intrínseco, en cuyo caso puede usar tscBefore = __rdtsc();
en lugar del bloque __asm
Ambos métodos son específicos de la plataforma y del compilador, desafortunadamente.
Estoy tratando de hacer un software C # que lea información sobre la CPU y se los muestre al usuario (al igual que CPU-Z). Mi problema actual es que no he podido encontrar la manera de mostrar la frecuencia de la CPU.
Al principio probé de la manera más fácil usando la clase Win32_Processor . Resultó muy eficiente, excepto si la CPU tiene overclock (o underclocked).
Luego, descubrí que mi registro contiene en HKLM / HARDWARE / DESCRIPTION / System / CentralProcessor / 0 el reloj "estándar" de la CPU (incluso si está overclockeado). El problema es que en las CPU modernas, el Multiplicador Core está disminuyendo cuando la CPU no necesita su máxima potencia, por lo que la Frecuencia de la CPU también está cambiando, pero el Valor en el Registro sigue siendo el mismo.
Mi próximo paso fue tratar de usar el RdTSC para calcular realmente la frecuencia de la CPU. Usé C ++ para esto porque puedo incrustarlo en un proyecto de C # si el método está funcionando. Encontré el siguiente código en http://www.codeproject.com/Articles/7340/Get-the-Processor-Speed-in-two-simple-ways, pero el problema era el mismo: el programa me da solo la frecuencia máxima (como en el valor de registro, diferencia de 1-2 Mhz) y también parece que carga la CPU más de lo que debería (incluso tuve picos de carga de CPU).
#include "stdafx.h"
#include <windows.h>
#include <cstdlib>
#include "intrin.h"
#include <WinError.h>
#include <winnt.h>
float ProcSpeedCalc() {
#define RdTSC __asm _emit 0x0f __asm _emit 0x31
// variables for the clock-cycles:
__int64 cyclesStart = 0, cyclesStop = 0;
// variables for the High-Res Preformance Counter:
unsigned __int64 nCtr = 0, nFreq = 0, nCtrStop = 0;
// retrieve performance-counter frequency per second:
if(!QueryPerformanceFrequency((LARGE_INTEGER *) &nFreq))
return 0;
// retrieve the current value of the performance counter:
QueryPerformanceCounter((LARGE_INTEGER *) &nCtrStop);
// add the frequency to the counter-value:
nCtrStop += nFreq;
_asm
{// retrieve the clock-cycles for the start value:
RdTSC
mov DWORD PTR cyclesStart, eax
mov DWORD PTR [cyclesStart + 4], edx
}
do{
// retrieve the value of the performance counter
// until 1 sec has gone by:
QueryPerformanceCounter((LARGE_INTEGER *) &nCtr);
}while (nCtr < nCtrStop);
_asm
{// retrieve again the clock-cycles after 1 sec. has gone by:
RdTSC
mov DWORD PTR cyclesStop, eax
mov DWORD PTR [cyclesStop + 4], edx
}
// stop-start is speed in Hz divided by 1,000,000 is speed in MHz
return ((float)cyclesStop-(float)cyclesStart) / 1000000;
}
int _tmain(int argc, _TCHAR* argv[])
{
while(true)
{
printf("CPU frequency = %f/n",ProcSpeedCalc());
Sleep(1000);
}
return 0;
}
También debería mencionar que probé el último método en una CPU AMD. También probé otros códigos para el método RdTSC, pero ninguno funcionaba correctamente.
Finalmente, traté de comprender el código utilizado para hacer este programa https://code.google.com/p/open-hardware-monitor/source/browse/ , pero era demasiado complejo para mí.
Entonces, mi pregunta es: ¿cómo determinar la frecuencia de la CPU en tiempo real (incluso cuando la CPU está overclockeada) usando C ++ o C #? Sé que esta pregunta fue hecha muchas veces, pero en realidad ninguna responde mi pregunta.
Tu pregunta es fundamentalmente incontestable. Las frecuencias de la CPU cambian constantemente. En ocasiones, el sistema operativo conoce los cambios y puede decírselo, pero a veces no. Las CPU pueden overclockearse a sí mismas (TurboBoost) o subclockearse (debido al sobrecalentamiento). Algunos procesadores reducen la potencia para evitar la fusión ejecutando el reloj a la misma velocidad pero solo trabajando en algunos ciclos, en cuyo punto el concepto completo de la frecuencia del reloj no tiene sentido.
En este post hablo de un número significativo de máquinas que analizo donde la CPU estaba siendo estrangulada térmicamente sin que Windows lo notara.
http://randomascii.wordpress.com/2013/08/06/defective-heat-sinks-causing-garbage-gaming/
Es posible escribir algún código desordenado que sea muy específico del procesador para detectar esto, pero requiere privilegios de administrador.
Mi punto es que estás haciendo una pregunta sin respuesta y, en la mayoría de los casos, no es una pregunta que deberías hacer. Use el valor en el registro o pregúntele a Windows con qué frecuencia funciona la CPU (ver PROCESSOR_POWER_INFORMATION) y llámelo lo suficientemente bueno.
La respuesta depende de lo que realmente quieras saber.
Si su objetivo es encontrar la frecuencia operativa de alguna aplicación en particular que esté ejecutando, entonces este es un problema difícil que requiere privilegios de administrador / raíz para acceder a registros específicos del modelo y tal vez incluso acceder al BIOS. Puede hacer esto con CPU-Z en Windows o powertop en Linux.
Sin embargo, si solo quieres saber la frecuencia de funcionamiento de tu procesador para uno o muchos hilos bajo carga para que puedas, por ejemplo, calcular los fracasos máximos (que es por lo que me importa esto), entonces esto se puede hacer con más o menos general código que no necesita privilegios de administrador.
Obtuve la idea del código de Bruce Dawson en http://randomascii.wordpress.com/2013/08/06/defective-heat-sinks-causing-garbage-gaming/ . Sobre todo extendí su código para trabajar con múltiples hilos usando OpenMP.
He probado esto en Linux y Windows en procesadores Intel, incluidos Nahalem, Ivy Bridge y Haswell con un socket de hasta cuatro sockets (40 hilos). Todos los resultados se desvían menos del 0.5% de la respuesta correcta.
Describí cómo determinar la frecuencia aquí how-can-i-programmatically-find-the-cpu-frequency-with-c así que no repetiré todos los detalles.