2008-09-26 5 views
7

En Win32, ¿hay alguna manera de obtener un recuento de ciclo de CPU único o algo similar que sería uniforme para múltiples procesos/idiomas/sistemas/etc.¿Cómo obtengo el recuento de ciclos de la CPU en Win32?

Estoy creando algunos archivos de registro, pero tengo que generar múltiples archivos de registro porque estamos organizando el tiempo de ejecución .NET, y me gustaría evitar llamar de uno a otro para iniciar sesión. Como tal, estaba pensando que solo produciría dos archivos, los combinaría y luego los ordenaría, para obtener una línea de tiempo coherente que implique llamadas en todo el mundo.

Sin embargo, GetTickCount no aumenta para cada llamada, por lo que no es confiable. ¿Hay un número mejor para recibir las llamadas en el orden correcto al ordenar?


Editar: Gracias a @Greg que me puso en el camino de QueryPerformanceCounter, que hizo el truco.

Respuesta

8

Puede usar la instrucción de CPU RDTSC (suponiendo x86). Esta instrucción proporciona el contador de ciclos de la CPU, pero tenga en cuenta que aumentará muy rápidamente a su valor máximo, y luego restablecer a 0. Como el artículo de Wikipedia menciona, es mejor que utilice la función QueryPerformanceCounter.

12

Heres an interesting article! dice no usar RDTSC, sino usar QueryPerformanceCounter.

Conclusión:

El uso regular de edad timeGetTime() hacer tiempo no es fiable en muchos sistemas operativos basados ​​en Windows debido a la granularidad del sistema temporizador puede ser tan alta como 10-15 milisegundos , lo que significa que timeGetTime() solo tiene una precisión de 10-15 milisegundos. [Tenga en cuenta que altas granularidades ocurren en sistemas operativos NT como Windows NT, 2000 y XP. Windows 95 y 98 tienden a tener mucho mejor granularidad, alrededor de 1-5 ms.]

Sin embargo, si se llama a timeBeginPeriod(1) al comienzo de su programa (y timeEndPeriod(1) en final), por lo general se timeGetTime() tenga una precisión de 1-2 milisegundos, y le proporcionará información de temporización extremadamente precisa .

Sleep() se comporta de manera similar; la longitud de tiempo que Sleep() realidad plazas para va mano a mano con el granularidad de timeGetTime(), así que después llamando timeBeginPeriod(1) una vez, Sleep(1) realmente dormir durante 1-2 milisegundos, Sleep(2) para 2-3, y entonces encendido (en lugar de dormir en incrementos de hasta 10-15 ms).

Para mayor precisión el tiempo (precisión sub-milisegundos), podrás probablemente desea evitar el uso del ensamblaje RDTSC mnemotécnico, ya que es difícil de calibrar ; en su lugar, use QueryPerformanceFrequency y QueryPerformanceCounter, que son con una precisión de menos de 10 microsegundos (0,00001 segundos).

Para sencilla momento, tanto timeGetTime y QueryPerformanceCounter funcionan bien, y QueryPerformanceCounter es obviamente más precisa. Sin embargo, si lo que necesita hacer ningún tipo de "cronometradas pausas" (tales como los necesarios para de imágenes por segundo limitante), tiene que ser cuidado de sentarse en un bucle llamando QueryPerformanceCounter, esperando que alcance un cierto valor; esto hará que consuma el 100% de su procesador. lugar, considere un esquema híbrido, donde usted llama Sueño (1) (no se olvide timeBeginPeriod (1) en primer lugar!) Siempre necesita pasar más de 1 ms de tiempo de , y sólo entrar en el QueryPerformanceCounter Bucle 100% -busy para finalizar el último < 1/1000 de un segundo de la demora que necesita. Este le proporcionará demoras ultraprecisas (con una precisión de 10 microsegundos), con uso muy mínimo de la CPU. Vea el código arriba.

+3

Por favor, evite timeBeginPeriod(); afecta el programador del sistema y puede causar problemas con el ahorro de energía. – MSalters

1

Utilice GetTickCount y agregue otro contador cuando fusione los archivos de registro. No le dará la secuencia perfecta entre los diferentes archivos de registro, pero al menos mantendrá todos los registros de cada archivo en el orden correcto.

+2

El conteo de ticks parece aumentar coincidiendo con el resultado en milisegundos, y es por eso que necesito algo un poco más preciso. –

2

System.Diagnostics.Stopwatch.GetTimestamp() devolver el número de ciclo de la CPU desde un origen de tiempo (tal vez cuando la computadora se inicia, pero no estoy seguro) y nunca lo he visto aumentado entre 2 llamadas.

Los ciclos de CPU serán específicos para cada computadora, por lo que no podrá usarlos para fusionar archivos de registro entre 2 computadoras.

+0

Gracias, solo fusionaré los archivos producidos en la misma computadora en el mismo marco de tiempo, así que eso funcionaría. Ahora solo necesito saber qué llama ese método en realidad :) –

2

La salida RDTSC puede depender de la frecuencia del reloj del núcleo actual, que para las CPU modernas no es constante ni, en una máquina multinúcleo, constante.

Utilice la hora del sistema, y ​​si se trata de fuentes de varios sistemas, utilice una fuente de tiempo NTP. Puede obtener lecturas de tiempo confiables y consistentes de esa manera; Si la sobrecarga es demasiado para sus propósitos, use HPET para calcular el tiempo transcurrido, ya que la última lectura de tiempo confiable conocida es mejor que usar HPET solo.

Cuestiones relacionadas