(不是严格的编程,而是程序员需要回答的问题。)
我有一个基准 X ,它由很多子基准 x 1 组成.. x <子>名词子> 即可。这是一个非常嘈杂的测试,结果变化很大。为了准确地进行基准测试,我必须减少“可变性”,这要求我首先测量变异性。
我可以使用标准差或方差轻松计算每个子基准的可变性。但是,我想得到一个代表整体变化的数字作为单个数字。
我自己对这个问题的尝试是:
sum = 0
foreach i in 1..n
calculate mean across the 60 runs of x_i
foreach j in 1..60
sum += abs(mean[i] - x_i[j])
variability = sum / 60
答案 0 :(得分:2)
最好的主意:ask at the statistics Stack Exchange once it hits public beta(一周内)。
与此同时:你可能实际上对变异的极端更感兴趣,而不是集中趋势(平均值等)。对于许多应用程序,我认为通过增加典型用户体验获得的收益相对较少,但通过改善最差用户体验可以获得很多收益。尝试标准偏差的第95百分位,并努力减少这一点。或者,如果典型的可变性 是您想要减少的,则将标准偏差绘制在一起。如果它们大致正常分布,我不知道为什么你不能采取平均值。
答案 1 :(得分:1)
我认为你误解standard deviation - 如果你运行你的测试50次并且有50个不同的运行时间标准偏差将是一个描述紧密或松散程度的数字这50个数字分布在你的平均值附近。结合平均运行时间,标准偏差将帮助您了解结果中的差异。
考虑以下运行时间:
12 15 16 18 19 21 12 14
这些运行时间的平均值为15.875
。该组的样品标准偏差为3.27。有一个很好的解释3.27实际上意味着什么(在正态分布的人口中,大约68%的样本将落在平均值的一个标准差内:例如,在15.875-3.27
和{{之间1}})但我认为你只是在寻找一种方法来量化你的平均值的“紧密”或“分散”结果。
现在考虑一组不同的运行时间(例如,在使用15.875+3.27
编译所有测试之后):
-O2
这些运行时间的平均值也是14 16 14 17 19 21 12 14
。该组的样品标准偏差为3.0。 (因此,大约68%的样本将落在15.875
和15.875-3.0
之内。)此集合比第一集更紧密。
你有一个数字可以概括一组数字的紧凑或松散程度。
<强>注意事项强>
标准差建立在假设normal distribution的基础上 - 但您的应用可能不是正常分布的,因此请注意标准偏差可能是最好的粗略指导。在histogram中绘制您的运行时间,以查看您的数据是否看起来大致正常或统一或多模式还是......
另外,我使用的是样本标准偏差,因为这些只是基准运行的人口空间中的样本。我不是一个专业的统计学家,所以即使这个基本假设也许是错误的。无论是人口标准偏差还是样本标准偏差都会在您的应用中为您提供足够好的结果。您坚持使用样本或人口。不要混淆两者。
我提到标准差与平均值一起将有助于您理解您的数据:如果标准偏差几乎与您的平均值一样大,或者更差,那么您的数据非常分散,也许你的过程不是很可重复。正如您所认识到的那样,面对大标准偏差解释15.875+3.0
加速几乎是无用的。而且,根据我的经验,最佳判断标准差的大小是平均值的大小。
最后注意:是的,您可以手动计算标准偏差,但在前十个左右后它会很繁琐。最好使用电子表格或wolfram alpha或你方便的高中计算器。
答案 2 :(得分:1)
来自Variance: “总组的方差等于子组方差的均值,再加上子组均值的方差。” 我不得不多次阅读,然后运行它:464来自这个公式== 464,所有数据的标准偏差 - 你想要的单个数字。
#!/usr/bin/env python
import sys
import numpy as np
N = 10
exec "\n".join( sys.argv[1:] ) # this.py N= ...
np.set_printoptions( 1, threshold=100, suppress=True ) # .1f
np.random.seed(1)
data = np.random.exponential( size=( N, 60 )) ** 5 # N rows, 60 cols
row_avs = np.mean( data, axis=-1 ) # av of each row
row_devs = np.std( data, axis=-1 ) # spread, stddev, of each row about its av
print "row averages:", row_avs
print "row spreads:", row_devs
print "average row spread: %.3g" % np.mean( row_devs )
# http://en.wikipedia.org/wiki/Variance:
# variance of the total group
# = mean of the variances of the subgroups + variance of the means of the subgroups
avvar = np.mean( row_devs ** 2 )
varavs = np.var( row_avs )
print "sqrt total variance: %.3g = sqrt( av var %.3g + var avs %.3g )" % (
np.sqrt( avvar + varavs ), avvar, varavs)
var_all = np.var( data ) # std^2 all N x 60 about the av of the lot
print "sqrt variance all: %.3g" % np.sqrt( var_all )
row averages: [ 49.6 151.4 58.1 35.7 59.7 48. 115.6 69.4 148.1 25. ]
row devs: [ 244.7 932.1 251.5 76.9 201.1 280. 513.7 295.9 798.9 159.3]
average row dev: 375
sqrt total variance: 464 = sqrt( av var 2.13e+05 + var avs 1.88e+03 )
sqrt variance all: 464
<小时/> 要查看组方差如何增加,请运行Wikipedia Variance中的示例。 假设我们有
60 men of heights 180 +- 10, exactly 30: 170 and 30: 190
60 women of heights 160 +- 7, 30: 153 and 30: 167.
平均标准差为(10 + 7)/ 2 = 8.5。 尽管如此,高度
-------|||----------|||-|||-----------------|||---
153 167 170 190
传播170 + - 13.2,远大于170 + - 8.5 为什么?因为我们不仅有传播男性+ - 10和女性+ - 7, 但也有160/180左右的普遍均值170的差价 练习:以两种方式计算传播13.2, 从上面的公式,直接。
答案 3 :(得分:0)
这是一个棘手的问题,因为基准测试无论如何都可以有不同的自然长度。因此,您需要做的第一件事是将每个单个子基准数字转换为比例不变的值(例如,相对于某些可信的良好基线的“加速因子”),这样您至少可以拥有机会比较不同的基准。
然后你需要选择一种方法来组合数字。某种平均水平。然而,有许多类型的平均值。我们可以拒绝使用模式和中位数;他们丢掉了太多相关信息。但是不同类型的均值是有用的,因为它们赋予异常值权重的方式不同。我曾经知道(但已经忘记了)在实践中最重要的是几何平均值还是调和平均值(这里的算术平均值不太好)。几何平均值基本上是对数域中的算术平均值,并且调和平均值类似于倒数域中的算术平均值。 (电子表格使这个变得微不足道。)
既然您已经有了将基准套件运行的值组合成适当信息的方法,那么您就可以进行大量的运行。您可能希望让计算机在执行其他任务时执行此操作。 :-)然后尝试以各种方式组合值。特别是,查看各个子基准的方差和组合基准数的方差。还要考虑在日志和互惠域中进行一些分析。
请注意,这是一项难以正确处理的业务,而且通常无法启动。基准测试仅对基准测试中的确切性能进行性能测试,而这主要不是人们如何使用代码。最好是严格考虑对基准工作进行时间限制,而是关注用户是否认为软件感知足够快或是否在部署中实际获得所需的事务率(有许多非编程搞砸事情的方法。)
祝你好运!答案 4 :(得分:-1)
你正试图解决错误的问题。最好尽量减少它。差异可能是因为缓存。
尝试在Windows上使用SetThreadAffinityMask()函数在单个(相同)核心上运行代码。
放弃第一次测量。
提高thead优先级。
停止超线程。
如果您有许多条件跳转,它可能会在具有不同输入的调用之间引入可见差异。 (这可以通过为第i次迭代提供完全相同的输入,然后比较这些迭代之间的测量时间来解决)。
您可以在此处找到一些有用的提示:http://www.agner.org/optimize/optimizing_cpp.pdf