我正在寻找在多核处理器上执行微基准测试的方法。
上下文
大约在同一时间,台式机处理器引入了无序执行,导致性能难以预测,他们或许并非巧合,还引入了特殊指令来获得非常精确的时序。这些说明的示例是x86上的rdtsc
和PowerPC上的rftb
。这些指令给出了比系统调用所允许的更精确的时序,允许程序员微观地对其心脏进行基准测试,无论好坏。
在具有多个内核的更现代的处理器上,其中一些内核在某些时候处于休眠状态,计数器在内核之间不同步。我们被告知rdtsc
不再可以安全地用于基准测试,但是当我们解释替代解决方案时,我一定是打瞌睡。
问题:
某些系统可能会保存并恢复性能计数器,并提供API调用以读取正确的总和。如果您知道此呼叫对于任何操作系统的影响,请在答案中告知我们。
某些系统可能允许关闭核心,只留下一个核心。我知道当从开发人员工具安装正确的首选项窗格时,Mac OS X Leopard会这样做。您是否认为这可以让rdtsc
安全再次使用?
更多背景信息:
请假设我在尝试进行微基准测试时知道自己在做什么。如果您认为如果无法通过计时整个应用程序来衡量优化的收益,那么不值得优化,我同意您的观点,但
在替代数据结构完成之前,我无法对整个应用程序进行计时,这将需要很长时间。事实上,如果微观基准没有希望,我现在可以决定放弃实施;
我需要在出版物中提供数据,其截止日期我无法控制。
答案 0 :(得分:2)
在OSX(ARM,Intel和PowerPC)上,您想使用mach_absolute_time( )
:
#include <mach/mach_time.h>
#include <stdint.h>
// Utility function for getting timings in nanoseconds.
double machTimeUnitsToNanoseconds(uint64_t mtu) {
static double mtusPerNanosecond = 0.0;
if (0.0 == mtusPerNanosecond) {
mach_timebase_info_data_t info;
if (mach_timebase_info(&info)) {
// Handle an error gracefully here, whatever that means to you.
// If you do get an error, something is seriously wrong, so
// I generally just report it and exit( ).
}
mtusPerNanosecond = (double)info.numer / info.denom;
}
return mtu * mtusPerNanosecond;
}
// In your code:
uint64_t startTime = mach_absolute_time( );
// Stuff that you want to time.
uint64_t endTime = mach_absolute_time( );
double elapsedNanoseconds = machTimeUnitsToNanoseconds(endTime - startTime);
请注意,没有必要为此限制一个核心。操作系统处理mach_absolute_time( )
幕后所需的修复,以便在多核(和多插槽)环境中提供有意义的结果。
答案 1 :(得分:1)
核心正在为“rtdsc”返回正确的同步值。如果您有多机器机器,则必须将过程固定到一个插槽。这不是问题。
主要问题是调度程序使数据不可靠。 Linux Kernel有一些性能API&gt; 2.6.31但我没有看过它。 Windows&gt; Vista在这里做得很好,使用QueryThreadCycleTime和QueryProcessCycleTime。
我不确定OSX,但AFAIK“mach_absolute_time”不会调整预定时间。