我知道我必须使用:rdtsc。测量的函数是确定性的,但结果远不是可重复的(我从运行到运行得到5%的振荡)。 可能的原因是:如何准确测量C++函数使用的时钟周期?
- 上下文切换
- 缓存未命中
你知道有其他原因? 如何消除它们?
我知道我必须使用:rdtsc。测量的函数是确定性的,但结果远不是可重复的(我从运行到运行得到5%的振荡)。 可能的原因是:如何准确测量C++函数使用的时钟周期?
你知道有其他原因? 如何消除它们?
TSC(rdtsc使用)通常在多处理器系统上不同步。它可能有助于设置CPU关联性,以便将进程绑定到单个CPU。
如果可以的话,您也可以从HPET timers得到时间戳,这些不容易出现同样的问题。
至于可重复性,这些差异是真实的。您可以禁用缓存,为进程提供实时优先级,和/或(如果在Linux或类似的环境中)用较低的固定计时器中断频率(时间片切片)重新编译内核。您不能完全消除差异,至少不容易,而不是常规的CPU + OS组合。
一般来说,为了简单的编码,可靠性和便携性的原因,我建议你使用操作系统所提供的。如果它提供高精度计时器,请使用适当的操作系统帮助程序。 (以防万一你想对加密系统进行一次时间攻击,那么你将不得不忍受1.这种随机性和2.一般的防御措施,因为很好的原因使系统变得不可预测,所以该功能可能不是关于时间的确定性。)
编辑:添加关于定时器操作系统可以提供的段落。
编辑:这是指Linux。为了将进程绑定到单个CPU(从RDTSC准确读取),可以使用sched_setaffinity(2)。而here的一些代码来自我的一个项目,用于其他目的(将线程映射到CPU)。这应该是你的第一次尝试。至于HPET,只要内核和机器支持这些定时器,就可以使用常规的POSIX调用,如these。
查看问题Is stopwatch benchmarking acceptable?了解现代多核多线程多进程机器上微基准测试的方差。
尽管问题是关于Java的,但这些考虑因素适用于任何语言的基准测试。
另见:How do I write a correct micro-benchmark in Java?
ALSE看到:What advice can you give me for writing a meaningful benchmark?
添加到的原因列表:分支预测/错误预测(这可以通过用某些芯片复预测缓存上下文切换来实现同样的预测可能会受到程序的不同输入的影响,因此两个不同数据集的时间之间的直接比较可能会略有偏差。
总的来说,减轻所有这些几乎是不可能的,但有些事情可以做到帮助每一个:
但是,当然,到目前为止,做这种定时的最好方法是在非常大的数据块上进行很多次处理,以使由无法控制的事物所引入的可变性最小化。 (它永远不会被真正擦除。)
如果您正在测量时钟周期,您为什么要消除缓存未命中并从基准中分支出错预测?这些也会在“野外”发生,所以重要的是要查看整个分布而不仅仅是最佳情况。 – Tom 2009-02-22 23:45:00
为什么要消除它们?听起来像你已经创造了一个现实的基准。该代码在野外使用时也会具有相同的可变性。可能更糟,因为您可能已经消除了磁盘和CPU缓存延迟。使用Jon Skeet的方法,创造条件让你获得最好的结果,只会让你感觉良好,但永远不可能实现。
如果绝对数字很重要,请计算中位数,而不是平均数。
大多数现代处理器都支持一组显着的低级硬件性能计数器。 如果你真的想知道答案,包括缓存未命中和上下文切换开销的实际测量结果,请抓住PAPI (Performance API) toolkit,然后在一些(尽管不是全部)操作系统上安装一个内核补丁,并且通过一些额外的努力,关闭和运行。
实际上在新的Linux内核中有新的perf子系统。例如:
$ ./perf stat du -s /tmp 94796 /tmp Performance counter stats for 'du -s /tmp': 2.546403 task-clock-msecs # 0.060 CPUs 3 context-switches # 0.001 M/sec 0 CPU-migrations # 0.000 M/sec 166 page-faults # 0.065 M/sec 2434963 cycles # 956.236 M/sec 1798092 instructions # 0.738 IPC 302969 branches # 118.979 M/sec 26197 branch-misses # 8.647 % 23217 cache-references # 9.118 M/sec 4621 cache-misses # 1.815 M/sec 0.042406580 seconds time elapsed
谢谢。如何将进程绑定到一个处理器?你有没有使用HPET的例子? – 2009-02-06 17:46:20
@ŁukaszLew:我编辑了我的文章并添加了详细信息。 – 2009-02-07 04:38:49
@ŁukaszLew:澄清了最后一段中的最佳方法和HPET。 – 2009-02-07 04:51:28