我正在为关键系统操作设计基准。理想情况下,基准可用于检测性能下降。我正在辩论是使用传递给该操作的较大工作负载的总时间,还是计算该操作所花费的周期作为基准的度量标准。
运行该操作的每个迭代的时间可能很快,大约为300-500纳秒。
答案 0 :(得分:1)
总时间更容易准确/可靠地测量,并且测量开销无关紧要。这是我的建议,只要您确定可以阻止编译器在要测量的所有迭代之间进行优化。 (如有必要,请检查生成的asm。)
如果您认为运行时可能与数据有关,并且希望研究迭代之间的差异,则可以考虑以某种方式记录时间戳。但是在3.3GHz的CPU上300 ns仅约1000个时钟周期,并且记录时间戳需要一些时间。因此,您绝对需要担心测量开销。
假设您使用的是x86,则每个操作周围的原始rdtsc
相当轻巧,但是乱序执行可能会使时间戳记随工作重新排序。 Get CPU cycle count?和clflush to invalidate cache line via C function。
lfence; rdtsc; lfence
会阻止工作负载的每次迭代重新安排时间,这会阻止工作负载步骤的无序执行,从而使事情失真。 (Skylake上的乱序执行窗口的ROB大小为224微秒。在每个时钟4个时,这是1k个时钟周期的一小部分,但是在吞吐量较低的代码中,由于缓存未命中而停顿,独立代码之间可能会出现明显的重叠迭代。)
任何标准计时功能,例如C ++ std::chrono
,通常都将调用最终使用rdtsc
的库函数,但带有许多额外的指令。或更糟糕的是,将使一个实际的系统调用花费一百多个时钟周期才能进入/离开内核,而启用Meltdown + Spectre缓解功能则需要更多时间。
但是,可能有用的一件事是使用Intel-PT(https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing)记录已采用分支上的时间戳。完全不阻塞无序的exec,您仍然可以获得重复循环中循环分支执行时的时间戳。这很可能与您的工作量无关,并且可以在它发布到内核的乱序部分之后立即运行,但是只能在最古老的尚未退休的指令之前有一段有限的距离。