2009-02-03 96 views

回答

5

TSC(rdtsc使用)通常在多处理器系统上不同步。它可能有助于设置CPU关联性,以便将进程绑定到单个CPU。

如果可以的话,您也可以从HPET timers得到时间戳,这些不容易出现同样的问题。

至于可重复性,这些差异是真实的。您可以禁用缓存,为进程提供实时优先级,和/或(如果在Linux或类似的环境中)用较低的固定计时器中断频率(时间片切片)重新编译内核。您不能完全消除差异,至少不容易,而不是常规的CPU + OS组合。

一般来说,为了简单的编码,可靠性和便携性的原因,我建议你使用操作系统所提供的。如果它提供高精度计时器,请使用适当的操作系统帮助程序。 (以防万一你想对加密系统进行一次时间攻击,那么你将不得不忍受1.这种随机性和2.一般的防御措施,因为很好的原因使系统变得不可预测,所以该功能可能不是关于时间的确定性。)

编辑:添加关于定时器操作系统可以提供的段落。

编辑:这是指Linux。为了将进程绑定到单个CPU(从RDTSC准确读取),可以使用sched_setaffinity(2)。而here的一些代码来自我的一个项目,用于其他目的(将线程映射到CPU)。这应该是你的第一次尝试。至于HPET,只要内核和机器支持这些定时器,就可以使用常规的POSIX调用,如these

+0

谢谢。如何将进程绑定到一个处理器?你有没有使用HPET的例子? – 2009-02-06 17:46:20

+0

@ŁukaszLew:我编辑了我的文章并添加了详细信息。 – 2009-02-07 04:38:49

+0

@ŁukaszLew:澄清了最后一段中的最佳方法和HPET。 – 2009-02-07 04:51:28

1

添加到的原因列表:分支预测/错误预测(这可以通过用某些芯片复预测缓存上下文切换来实现同样的预测可能会受到程序的不同输入的影响,因此两个不同数据集的时间之间的直接比较可能会略有偏差。

总的来说,减轻所有这些几乎是不可能的,但有些事情可以做到帮助每一个:

  • 缓存小姐:“总理”开始时期之前的高速缓存。不要忘记还有一个指令缓存也需要启动。对于小型数据集,只需运行一次完整的测试,无需计时,然后再次运行。对于大数据集,执行此操作,然后使用处理器的预缓存指令将第一个数据块加载回缓存。
  • 上下文切换:在轻载系统上使用多处理器/内核芯片,并将进程的亲和性设置为特定的CPU(最好不是CPU 0)。这也有助于缓存未命中(因为移动CPU意味着缓存完全丢失)和分支预测(因为它实际上是一种缓存形式)。

但是,当然,到目前为止,做这种定时的最好方法是在非常大的数据块上进行很多次处理,以使由无法控制的事物所引入的可变性最小化。 (它永远不会被真正擦除。)

+0

如果您正在测量时钟周期,您为什么要消除缓存未命中并从基准中分支出错预测?这些也会在“野外”发生,所以重要的是要查看整个分布而不仅仅是最佳情况。 – Tom 2009-02-22 23:45:00

2

为什么要消除它们?听起来像你已经创造了一个现实的基准。该代码在野外使用时也会具有相同的可变性。可能更糟,因为您可能已经消除了磁盘和CPU缓存延迟。使用Jon Skeet的方法,创造条件让你获得最好的结果,只会让你感觉良好,但永远不可能实现。

如果绝对数字很重要,请计算中位数,而不是平均数。

0

大多数现代处理器都支持一组显着的低级硬件性能计数器。 如果你真的想知道答案,包括缓存未命中和上下文切换开销的实际测量结果,请抓住PAPI (Performance API) toolkit,然后在一些(尽管不是全部)操作系统上安装一个内核补丁,并且通过一些额外的努力,关闭和运行。

2

实际上在新的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