基准考虑因素和确定性数据收集

时间:2011-07-15 05:41:19

标签: c++ benchmarking

我正在编写一个c ++基准测试程序,它涉及计时许多函数调用。重复调用这些函数,并且每次记录这些函数以便稍后进行统计分析。要求功能在多个线程上同时运行,从而确保基准测试的准确性和公平性,它在实时操作系统上运行,并且控制调度行为。以下是我的担忧:

是否有收集时间数据的确定方法?我查看了printf和stringstream,但由于内存和放大器似乎都没有确定性行为。缓冲操作。由于同样的原因,他们也没有在O(1)中表演,对吗?目前我正在使用大型char数组和自定义strcat函数,以便可以在O(1)中收集每个时间值。然后在测试结束时打印此数组,此时已收集所有数据。

我正在使用clock_gettime作为时间安排,clock_getres给出了1ns的分辨率。这个值可以信任吗?

到目前为止我做得对吗,在编写基准时我还应该注意其他任何问题吗?

2 个答案:

答案 0 :(得分:1)

调用高频定时器并将样本写入输出流是获得性能数据的一种非常明智的方法。但是有一些棘手的问题要小心。

  • 确实你不应该使用printf和stringstream - 不仅因为它们的执行时间是可变的而且定义不明确,而且因为它们只是非常慢,特别是如果你将每个微秒的perf数据格式化为字符串!将二进制数据写入预分配的缓冲区(如结构数组),然后在测试完成后再格式化它们要好得多。这将更快,并为您提供更一致的写入开销。
  • 如果编写内核的人不是傻瓜,那么使用高分辨率计时器(例如CLOCK_PROCESS_CPUTIME_ID)的
  • clock_gettime应该是可靠的。如果要直接查询CPU计时器,可以查看Performance Application Programming Interface库,但这不是必需的。
  • 多线程可能本质上是混乱的(在确定性意义上),因为线程相互争用CPU缓存和内存带宽。您可以获得随机变化的结果,具体取决于同时调度的线程是否碰巧触及相同的内存,或者是否始终从数据缓存中驱逐彼此的工作 - 这将根据数据的确切排列方式而有所不同。在内存中以及正在运行的线程。但这没关系:工程中的许多流程都是随机的。只需多次运行基准测试,就可获得统计上显着的平均值和偏差数。

或者,如果您确实需要100%确定性,则需要确保线程以相同的顺序安排,运行相同的量子,并将每个运行的数据放在相同的内存地址中。 / p>

答案 1 :(得分:0)

使用big-O表示法来考虑现实生活中的问题。

对于问题的其余部分说:

性能收集需要一些时间(O(1)仍然可能是有意义的时间,只是它不依赖于您的数据)。你需要使它最有效率。

这意味着:

  1. 不要使用printf喜欢,而是写入特殊的记忆区域,稍后您将从中提取数据。

  2. 出于同样的原因,请不要使用strcat,而是使用struct的二进制数据。你完成后最后解析它。

  3. 不是衡量每次通话,而是考虑衡量平均值(即:衡量不是每次通话,而是每1000次和平均值来提取单次通话的近似费用)。这将使您的测量开销时间减少。但这并非总是可行,但请考虑一下。

  4. clock_gettime通常可以信任,但这取决于您的操作系统和硬件 - 检查它们,有时硬件时钟分辨率可能没有您想要的那么小。