2011-11-28 9 views
10

Adopté en línea para medir el rendimiento de SSE.¿Es esta marca de reloj adecuada para Intel i3?

#ifndef __TIMER_H__ 
#define __TIMER_H__ 

#pragma warning (push) 
#pragma warning (disable : 4035) // disable no return value warning 

__forceinline unsigned int GetPentiumTimer() 
{ 
    __asm 
    { 
     xor eax,eax    // VC won't realize that eax is modified w/out this 
            // instruction to modify the val. 
            // Problem shows up in release mode builds 
     _emit 0x0F    // Pentium high-freq counter to edx;eax 
     _emit 0x31    // only care about low 32 bits in eax 

     xor edx,edx    // so VC gets that edx is modified 
    } 
} 

#pragma warning (pop) 

#endif 

lo hice la medición en mi CPU Pentium E2200 D, y funciona bien (que muestra instrucciones SSE alineados son más rápidos). Pero en mi CPU i3 recibo instrucciones desalineadas más rápido el 70% de las pruebas.

¿Ustedes piensan que esta medida de la señal del reloj no es adecuada para la CPU i3?

+0

Estoy bastante seguro de que VC admite la instrucción 'RDTSC' en el ASM en línea. Además, ¿por qué no te importan los bits superiores de 32, y debes usar '__declspec (naked)' o incluso mejor devolver un valor de una manera más adecuada. Además, me gustaría utilizar ['QueryPerformanceCounter'] (http: //msdn.microsoft.com/en-us/library/windows/desktop/ms644904 \ (v = vs.85 \).aspx) o funciones similares en su lugar (teniendo en cuenta los problemas con la escala de frecuencia/procesadores multi-core, etc.). – user786653

+0

RDTSC es * no * una instrucción de serialización, lo que significa que puede/se ejecutará fuera de servicio. Si insiste en usarlo directamente, generalmente quiere usar CPUID para forzar la serialización (es una de las pocas instrucciones de serialización que puede ejecutar en el modo de usuario). –

+0

Tengo QueryPerformanceCounter también. No es muy confiable según los resultados. Para la multiplicación de nxn matrices, n = 10000 o más, el tiempo toma solo 0.3 segundos? No creo que eso sea preciso en absoluto (en la consola lleva más de 2 segundos ver los resultados), así que me dirijo a los ticks del reloj. Voy a probar RDTSC ahora. Gracias. – CppLearner

Respuesta

4

QueryPerformanceCounter (en Windows por lo menos) es definitivamente mucho mejor que el ensamblador en línea. No veo ninguna razón para utilizar el ensamblado en línea (que le dará problemas para compilar x64 en Visual Studio que no admite el ensamblado en línea) sobre esa función.

2

Como se ha notado, debe usar QueryPerformanceCounter.

pero si realmente desea utilizar ensamblador, lo mejor es utilizar puede ser el __rdtsc intrínseca.

Si usted no desea utilizar el la intrínseca, entonces esto sería la mejor aproach:

unsigned __int64 __declspec(naked) GetPentiumTimer() { 
    __asm { 
     rdtsc 
     ret 
    } 
} 

Por mis conocimientos de Visual C++ se niega a hacer en línea para cualquier función que está utilizando ensamblador en línea de todos modos. Al usar __declspec (naked) le diría al compilador que maneje correctamente el uso del registro.

Pero el uso de la intrínseca sería lo mejor, de esta manera el compilador saber qué registros se utilizan y se colocarán en línea de la manera adecuada.

1

0F 31, que es la instrucción RDTSC, aún puede ser útil para medir el rendimiento de fragmentos cortos de código. Incluso para CPU i3. Si los efectos del cambio de tareas y la migración del hilo a un núcleo diferente no le molestan, está bien usar RDTSC. En muchos casos, obtiene resultados más precisos forzando la serialización con CPUID.

En cuanto a sus medidas, es muy posible que desalineada SSE está trabajando más rápido en i3. Los últimos procesadores Intel (arquitecturas Nehalem y Sandy Bridge) pueden manejar operandos de memoria mal alineados de manera muy eficiente. Definitivamente, nunca superarán las instrucciones alineadas, pero si algunos otros factores influyen en el rendimiento en sus pruebas, las instrucciones alineadas pueden parecer más lentas.

Editar:

Ver http://www.agner.org/optimize/#testp. Es un buen ejemplo del uso de la instrucción RDTSC.

0

QueryPerformanceCounter() es la forma más sencilla de obtener un temporizador de alta frecuencia en Windows. Sin embargo, tiene un poco de sobrecarga, ya que es una llamada al sistema — about & frac12; μ s. Eso puede ser un problema si estás cronometrando eventos muy rápidos o si necesitas mucha precisión.

Si necesita más de 250 nanosegundos de precisión, puede utilizar the rdtsc intrinsic para obtener el contador de hardware directamente. Son aproximadamente 10 segundos de latencia en mi i7.

Cuestiones relacionadas