我即将在C中开始对一组复杂函数进行非常详细的基准测试。这是“科学水平”的细节。我想知道,进行严格基准测试的最佳方法是什么?我正在考虑运行它们,比如每次运行10次,平均时间结果并给出标准开发,例如,只使用<time.h>
。你们会做些什么来获得良好的基准?
答案 0 :(得分:7)
当相关分布大致正常时,报告平均值和标准差可以很好地描述分布。但是,计算性能测量很少这样。相反,性能测量倾向于更接近泊松分布。这是有道理的,因为计算机上没有多少随机事件会导致程序更快;基本上所有的测量噪声都是在多少随机事件发生导致它减速的情况下。 (相比之下,正态分布使得根本不具有直觉意义;它需要相信程序在负时间内具有非零概率的完成。)
鉴于此,我发现在程序的多次运行中报告最小时间非常有用,而不是平均值;分布中的噪声通常是测量系统的噪声,而不是有关算法的有意义的信息。对于具有早期条件和其他快捷方式的复杂算法,您需要更加小心,但是每次运行处理代表性输入平衡的许多运行的最小值通常都很有效。
“每次10次”听起来像非常几次迭代给我。我通常会做大约数千(或更多,取决于功能/系统)的运行,除非这是完全不可行的。至少,您需要确保运行时间足够长,以消除对系统状态的任何依赖,其中一些可能会在相当大的时间粒度下发生变化。
您应该注意的另一件事是,基本上每个系统都有一个特定于平台的计时器,它比可用的<time.h>
准确得多。找出目标平台上的内容并改为使用它。
答案 1 :(得分:0)
我假设您正在考虑在程序中对纯算法计算进行基准测试,并且没有用户输入或输出可能会花费不可预测的时间。 现在对于纯数字运算程序,您的结果可能会根据程序实际运行的时间而有所不同,这将受到系统中其他正在进行的活动的影响。根据所需的准确度水平,可能还有其他因素可能会忽略,即由于高速缓存未命中而产生的影响,通过存储器层次结构的不同访问时间“ 其中一种方法是建议在多次运行中计算平均值。 或者您可以尝试查看汇编代码并查看生成的指令。然后根据处理器获取这些指令的循环计数。此方法可能不实用,具体取决于您要基准的代码量。如果您特别关注内存层次结构影响,那么您可能需要非常小心地控制执行环境,即加载程序的位置,加载数据的位置等。但正如我所提到的,根据所需的准确性,您可能会吸收由于内存引起的变化统计变异中的等级“。 您可能需要为您的功能仔细设计测试输入以确保路径覆盖,并可以选择发布作为测试输入函数的性能统计信息。这将显示函数在输入范围内的行为