这个时钟滴答适用于 Intel i3 吗?
Posted
技术标签:
【中文标题】这个时钟滴答适用于 Intel i3 吗?【英文标题】:Is this clock tick suitable on Intel i3? 【发布时间】:2011-11-28 18:20:34 【问题描述】:我采用在线方式来衡量 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 吗?
【问题讨论】:
我很确定 VC 支持内联 asm 中的RDTSC
指令。另外,您为什么不关心高 32 位,您应该使用 __declspec(naked)
或者更好地以更适当的方式返回一个值。此外,我想改用QueryPerformanceCounter
或类似功能(注意频率缩放/多核处理器等问题)。
RDTSC 不是序列化指令,这意味着它可以/将被乱序执行。如果你坚持直接使用它,你通常希望使用 CPUID 来强制序列化(它是你可以在用户态执行的少数序列化指令之一)。
我也有 QueryPerformanceCounter。根据结果,它不是很可靠。对于 nxn 矩阵乘法,n = 10000 或更高,时间只需要 0.3 秒?我认为这根本不准确(在控制台上看到结果需要超过 2 秒),所以我转向时钟滴答。我现在要试试 RDTSC。谢谢。
我还推荐QueryPerformanceCounter
,假设这是 Windows 平台。
如果你想使用原始rdtsc
,请使用__rdtsc()
内在函数。 Get CPU cycle count?
【参考方案1】:
QueryPerformanceCounter(至少在 Windows 上)绝对比内联汇编好得多。我看不出有任何理由在该函数上使用内联汇编(这会给您在不支持内联汇编的 Visual Studio 上编译到 x64 时出现问题)。
【讨论】:
【参考方案2】:0F 31 是 RDTSC 指令,对于测量短代码段的性能仍然可能有用。即使对于 i3 CPU。如果任务切换和将线程迁移到不同内核的影响不打扰您,则可以使用 RDTSC。在许多情况下,强制使用 CPUID 进行序列化会得到更精确的结果。
至于您的测量,很有可能未对齐的 SSE 在 i3 上运行得更快。最新的英特尔处理器(Nehalem 和 Sandy Bridge 架构)可以非常有效地处理未对齐的内存操作数。当然,它们永远不会胜过对齐指令,但如果其他一些因素影响测试中的性能,对齐指令可能会看起来更慢。
编辑:
见http://www.agner.org/optimize/#testp。这是RDTSC指令使用的一个很好的例子。
【讨论】:
【参考方案3】:正如其他人注意到的那样,您应该使用 QueryPerformanceCounter。
但如果你真的想使用汇编程序,最好的可能是使用内在的 __rdtsc。
如果你不想使用内在函数,那么这将是最好的方法:
unsigned __int64 __declspec(naked) GetPentiumTimer()
__asm
rdtsc
ret
据我所知,Visual C++ 拒绝对任何使用内联汇编程序的函数执行内联。通过使用 __declspec(naked),您可以告诉编译器正确处理寄存器的使用。
但是使用内在函数是最好的,这样编译器就会知道使用了哪些寄存器,并以正确的方式内联。
【讨论】:
不,MSVC 可以内联使用__asm
的函数,如果你不将它们设为naked
。但绝对使用__rdtsc
内在;它可以跨 32 / 64 位移植,并且可以移植到 gcc/clang/ICC。 Get CPU cycle count?【参考方案4】:
QueryPerformanceCounter() 是在 Windows 上获取高频计时器的最简单方法。然而,它有一点开销,因为它是一个系统调用——大约 ½μs。如果您正在为非常快的事件计时,或者需要非常高的精度,这可能是个问题。
如果您需要优于 250 纳秒的精度,您可以使用the rdtsc intrinsic 直接获取硬件计数器。我的 i7 大约有 10ns 的延迟。
【讨论】:
rdtsc
没有输入,所以我猜它的延迟会从问题到输出寄存器准备好。仅在分支未命中或其他前端失速后才有意义,并且难以衡量。也许您的意思是吞吐量?以上是关于这个时钟滴答适用于 Intel i3 吗?的主要内容,如果未能解决你的问题,请参考以下文章