我在线采用衡量SSE表现的方法。
#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
我在Pentium D E2200 CPU上进行了测量,并且工作正常(它显示对齐的SSE指令更快)。 但是在我的i3 CPU上,我得到了70%的测试更快的未对齐指令。
你们认为这种时钟滴答测量不适合i3 CPU吗?
答案 0 :(得分:4)
QueryPerformanceCounter(至少在Windows上)肯定比内联汇编好得多。我看不出有任何理由在该函数上使用内联汇编(这将使您在Visual Studio上编译x64,而不支持内联汇编)。
答案 1 :(得分:2)
正如其他人注意到的,你应该使用QueryPerformanceCounter。
但是如果你真的想使用汇编程序,那么最好的可能就是使用内在的__rdtsc。
如果你不想使用内在的,那么这将是最好的方法:
unsigned __int64 __declspec(naked) GetPentiumTimer() {
__asm {
rdtsc
ret
}
}
据我所知,Visual C ++拒绝为任何使用内联汇编程序的函数进行内联。通过使用__declspec(裸),您可以告诉编译器正确处理寄存器使用情况。
但是使用内在函数是最好的,这样编译器就会知道使用了哪些寄存器并以正确的方式内联。
答案 2 :(得分:2)
0F 31,即RDTSC指令,仍然可用于测量短代码的性能。即使是i3 CPU。如果任务切换和迁移线程到不同核心的影响不打扰你,可以使用RDTSC。在许多情况下,您可以获得更精确的结果,强制使用CPUID进行序列化。
对于您的测量,很可能未对准的SSE在i3上运行得更快。最新的英特尔处理器(Nehalem和Sandy Bridge架构)可以非常有效地处理未对齐的内存操作数。当然,它们永远不会胜过对齐指令,但如果其他一些因素会影响测试中的性能,那么对齐的指令似乎运行得更慢。
修改强>
见http://www.agner.org/optimize/#testp。这是RDTSC指令使用的一个很好的例子。
答案 3 :(得分:1)
QueryPerformanceCounter()是在Windows上获取高频计时器的最简单方法。但是,它有一点开销,因为它是一个系统调用 - 大约½μs。如果您计时非常快,或者需要非常高的精度,这可能是一个问题。
如果您需要高于250纳秒的精度,可以使用the rdtsc intrinsic直接获取硬件计数器。我的i7上有大约10ns的延迟。