【问题标题】:How do I measure variability of a benchmark comprised of many sub-benchmarks?如何测量由许多子基准组成的基准的可变性?
【发布时间】:2010-07-22 08:52:51
【问题描述】:

(不是严格意义上的编程,而是程序员需要回答的一个问题。)

我有一个基准 X,它由许多子基准 x1..x 组成n。这是一个相当嘈杂的测试,结果变化很大。为了准确地进行基准测试,我必须减少“可变性”,这需要我首先测量可变性。

我可以使用标准偏差或方差轻松计算每个子基准的可变性。但是,我想得到一个数字,它将整体可变性表示为一个数字。

我自己对这个问题的尝试是:

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

【问题讨论】:

  • 您在寻找Standard deviation吗?
  • @Johannes:我可以很容易地得到 n 个标准差,然后呢?我如何将它们结合起来?我很确定对它们进行平均是不对的……
  • 我建议增加运行次数(1k+),然后使用箱线图分析您的结果。有一些免费的统计应用程序会对您有很大帮助。
  • @InsertNickHere:好主意,但我真的想得到一个数字。
  • 实际上与品种无关。请您澄清一下基准 x1..xn 的实际作用?您是否在多用户环境中运行基准测试?您测试哪种应用程序:CPU 密集型或 I/O 密集型还是其他?

标签: performance optimization statistics benchmarking measurement


【解决方案1】:

最佳创意:ask at the statistics Stack Exchange once it hits public beta(一周内)。

与此同时:您实际上可能对变异性的极端更感兴趣,而不是集中趋势(均值等)。对于许多应用程序,我认为通过增加典型用户体验可以获得相对较少的收益,但通过改善最差用户体验可以获得很多。尝试标准偏差的第 95 个百分位并努力减少它。或者,如果典型的可变性您想要减少的,则将标准差全部绘制在一起。如果它们是近似正态分布的,我不知道你为什么不能取平均值。

【讨论】:

【解决方案2】:

我认为您误解了 standard deviation -- 如果您运行测试 50 次并有 50 个不同的运行时,标准差将是一个数字,描述这 50 个的松紧程度数字分布在您的平均值附近。结合您的平均运行时间,标准差将帮助您了解结果的分散程度。

考虑以下运行时间:

12 15 16 18 19 21 12 14

这些运行时间的平均值是15.875。该集合的样本标准差为 3.27。对 3.27 的实际含义有一个很好的解释意味着(在一个正态分布的总体中,大约 68% 的样本将落在平均值的一个标准差内:例如,在 15.875-3.2715.875+3.27 之间)但我认为您只是在寻找一种方法来量化结果在您的均值附近的“紧密”或“分散”程度。

现在考虑一组不同的运行时间(例如,在您使用 -O2 编译所有测试之后):

14 16 14 17 19 21 12 14

这些运行时间的平均值也是15.875。该集合的样本标准差为 3.0。 (因此,大约 68% 的样本将属于 15.875-3.015.875+3.0。)这组比第一组更紧密地分组。

你有一个数字来总结一组数字在均值附近的紧凑或松散程度。

注意事项

标准差建立在normal distribution 的假设之上——但您的应用程序可能不是正态分布的,因此请注意,标准差最多可能只是一个粗略的指导。在 histogram 中绘制您的运行时间,以查看您的数据是否看起来大致正常或统一或多模式或...

另外,我使用的是样本标准差,因为这些只是基准运行总体空间中的一个样本。我不是专业的统计学家,所以即使是这个基本假设也可能是错误的。如果您坚持样本或总体,总体标准差或样本标准差都会在您的应用程序中为您提供足够好的结果。不要将两者混为一谈。

我提到,标准差与平均值一起有助于您理解数据:如果标准差几乎与平均值一样大,或者更糟,更大,那么您的数据非常分散,也许你的过程不是很可重复。正如您所认识到的,面对较大的标准偏差解释3% 加速几乎是无用的。标准偏差大小的最佳判断(根据我的经验)是平均值的大小。

最后一点:是的,您可以手动计算标准差,但是在前十个左右之后就很乏味了。最好使用电子表格或 wolfram alpha 或方便的高中计算器。

【讨论】:

  • 我确实了解标准偏差。但是,我的问题是我有 26 个发行版,并且想将它们组合成一个方便的数字。我解释了完整的问题,因为我对统计数据的理解不够深入,无法知道组合一组标准差是否有任何意义。
  • @Paul,好的,现在我明白了。我以为您不确定如何将多次运行 X 的时间转换为 X 可变性的度量。但是您想将数十个子测试的可变性组合成比 X 的可变性更有意义的东西。而且也绝对超出了我的统计范围。
  • 好的,谢谢。我重写了这个问题,以更仔细地描述我需要什么。感谢您的帮助。
【解决方案3】:

来自Variance: “总组的方差等于子组方差的均值加上子组均值的方差。” 我不得不读了好几遍,然后运行它:464 from this formula == 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, 从上面的公式,直接。

【讨论】:

  • 谢谢,很好的答案。我查看了维基百科页面,但我不确定。该引用由以下条件决定:“假设可以根据某个第二个变量将观察结果划分为大小相等的子组。”这就是我对基准的看法吗?从这个意义上说,每个“子基准”是一个子组吗?我认为 Bienaymé 公式可能更接近:“不相关随机变量之和的方差是它们的方差之和”。所以问题是他们是独立的。我认为是的,因为无法从另一个子基准预测一个子基准的结果。想法?
  • @Paul,是的,您有子组,如男性/女性示例(改进了一点)。我建议绘制你的数据,N 条水平线,每条 60 个点,以查看它们是如何分散的;铅笔和纸,一些数据就足够了。关于“总和的方差......”:我们没有在任何地方添加数字? (如果答案有用,请点击“接受”。)
【解决方案4】:

这是一个棘手的问题,因为基准无论如何都可以具有不同的自然长度。因此,您需要做的第一件事是将每个单独的子基准数字转换为比例不变的值(例如,相对于某些认为良好的基线的“加速因子”),以便您至少有一个 机会比较不同的基准。

然后你需要选择一种方法来组合这些数字。某种平均水平。然而,有许多类型的平均值。我们可以在这里拒绝使用众数和中位数;他们丢弃了太多相关信息。但是不同类型的平均值很有用,因为它们赋予异常值权重的方式不同。我曾经知道(但忘记了)在实践中最有用的是几何平均值还是调和平均值(算术平均值在这里不太好)。几何平均值基本上是对数域中的算术平均值,调和平均值同样是倒数域中的算术平均值。 (电子表格使这变得微不足道。)

既然您有办法将运行基准套件的值组合成适当的信息,那么您必须进行大量运行。您可能希望在您继续执行其他任务时让计算机执行此操作。 :-) 然后尝试以各种方式组合这些值。特别是,查看各个子基准的方差和组合基准数的方差。还可以考虑在对数和倒数域中进行一些分析。

请注意,这是一项缓慢的业务,很难做到正确,而且通常无法启动。基准测试只对基准测试中的内容进行性能测试,而这主要不是人们使用代码的方式。最好考虑对您的基准测试工作进行严格的时间限制,而不是关注用户是否认为软件足够快感知,或者在部署过程中是否实际达到了所需的事务率(有许多非编程把事情搞砸的方法)。

祝你好运!

【讨论】:

    【解决方案5】:

    您正在尝试解决错误的问题。最好尽量减少它。差异可能是由于缓存。

    尝试在 Windows 上使用 SetThreadAffinityMask() 函数在单个(相同)内核上运行代码。

    放弃第一次测量。

    提高主题优先级。

    停止超线程。

    如果您有许多条件跳转,则可能会在具有不同输入的调用之间引入明显的差异。 (这可以通过为第 i 次迭代提供完全相同的输入,然后比较这些迭代之间的测量时间来解决)。

    您可以在这里找到一些有用的提示:http://www.agner.org/optimize/optimizing_cpp.pdf

    【讨论】:

    • 无法测量如何最小化?
    • 我的意思是可变性。据我了解,您希望能够看到速度的微小改进,但由于测量值的巨大差异,您无法做到(噪声>>信号强度)。所以你决定找到测量平均值的最佳方法。我的观点是,您最好尝试使用这些提示来最小化可变性(或噪音),这样您就不需要复杂的方法来计算平均值。
    • 不,我正在尝试测量可变性,以便减少它。
    • 以上所有提示都是减少可变性的方法。
    • 对,但我需要对其进行测量以了解我减少它的尝试是否成功。
    猜你喜欢
    • 2015-11-08
    • 2017-11-07
    • 2014-12-19
    • 2020-09-27
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2017-05-14
    • 2017-05-29
    相关资源
    最近更新 更多