我正在编写一个c++基准测试程序,其中涉及对许多函数调用进行计时。这些函数被重复调用,并且每次都被记录下来以便以后进行统计分析。要求功能在多个线程上同时运行,因此为了确保基准的准确性和公平性,必须在实时OS上运行基准,并控制调度行为。以下是我的担忧:

是否存在确定性的计时数据收集方式?我看过printf和stringstream,但是由于内存和缓冲区操作,它们似乎都没有确定性的行为。由于同样的原因,它们也不会在O(1)中执行,对吗?当前,我正在使用一个大的char数组和一个自定义的strcat函数,以便可以在O(1)中收集每个时间值。当所有数据收集完毕后,在测试结束时打印该阵列。

我使用clock_gettime计时,而clock_getres给我1ns的分辨率。可以信任此值吗?

到目前为止,我做的事情是否正确,编写基准测试时还有其他问题要注意吗?

最佳答案

调用高频定时器并将样本写入输出流是获取性能数据的一种非常明智的方法。但是,有一些棘手的陷阱需要注意。

  • 实际上,您不应该使用printf和stringstream -不仅是因为它们的执行时间是可变的且定义不当,而且还因为它们的执行速度很慢,尤其是当您将perf数据每微秒格式化为字符串时!最好将二进制数据写入预分配的缓冲区(如结构数组),然后在测试完成后格式化它们。这样会更快,并为您提供更一致的写入开销。
  • 如果编写内核的人不是笨拙的人,那么带有高分辨率计时器的
  • clock_gettime(例如CLOCK_PROCESS_CPUTIME_ID)应该是可靠的。如果要直接查询CPU计时器,可以查看Performance Application Programming Interface库,但这不是必需的。
  • 多线程处理从本质上讲是混乱的(在确定性意义上),因为线程之间在争用CPU缓存和内存带宽。您可能会获得随机变化的结果,具体取决于同时调度的线程是否碰触相同的内存,还是一直在从数据缓存中逐出彼此的工作-每次运行都会有所不同,具体取决于数据的放置方式在内存中以及哪些线程正在运行。但这很好:工程中的许多过程都是随机的。只需多次运行基准测试,即可获得具有统计意义的平均值和性能偏差。

  • 或者,如果您确实需要100%的确定性,则需要确保线程以相同的顺序进行调度,以相同的数量运行,并将其数据放置在每次运行的相同内存地址中。

    关于c++ - 标杆考量和确定性数据收集,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6703128/

    10-11 22:49
    查看更多