一、问题引入:
比较使用两种不同算法写出的相同效果的函数孰优孰劣、或者是只是探究编程语言的性质单纯比较两种代码写法谁快谁慢,这是很常见的需求。显然,最简单的方法是重复两个函数足够多的次数(比如一百万次),然后单纯地比较耗时的多与少。
但是存在对于某些比较精细的问题,两种的耗时可能相差非常之小,以至于直观感觉很可能误以为是误差的情况,比如,当两者的差距只有,假设是0.2%的情况下,直觉会让我们忽略这一差距,或者归类为误差,或者认为其差距不足以产生定性影响。
但究竟能否分出高下呢?考虑这种情况:差距是0.2%,但在测试一千次的情况下,函数A总比函数B稳定地快出0.2%,很显然,这时虽然差距很小,但是我们还是可以有把握地说,函数A大概率比函数B有独到之处,函数A更优,尽管幅度不大。
由此可见,这时候,简单直观的方法就失效了,而概率论和数理统计方法为解决这一问题提供了强大的工具。本文试图将概率论和数理统计方法应用到这一问题上,本人所学有限,如有任何错误、疏漏,请不吝赐教。
二、理论依据:
正态分布、t分布、假设检验
三、具体思路:
方法一:双正态总体模型
1.基本假设:
设函数,
的计时结果分别为
,
。
- 设对于一个单一函数,计时的误差服从以0为中心的正态分布,即
- 设函数的运行时长为一常数
,则测量值
,则
- 设两函数计时结果的方差相等,即
由于在同一机器上测试,有理由认为假设3是对的,另外,如果没有假设3,我就不会算了哈哈。
2.假设检验:
由于所研究的问题是函数,
“孰优孰劣”的问题,不是“是否有差别”的问题,所以选择单侧检验。在实际实验中,通常存在一方比另一方快的假设(如在一次测量结果后,我们总可以提出假设,假设平均值较少的函数更快),所以在这里不妨假设
比
快。
则对于显著性水平:
- 原假设:
不比
快,即
- 备择假设:
比
快,即
取检验统计量 ,其中
则服从t分布,即
所以拒绝域为
所以,如果让计算机自动判断,只需求出这个
和t分布的分位点值,就可以做出定性结论。
方法二:配对检验模型
当我想出这个方法时,我自己也很吃惊,但是我自己又找不出漏洞,这个方法的可靠性还需高人进一步论证。
1.基本假设:
设函数,
的计时结果分别为
,
。
- 设对于一个单一函数,计时的误差服从以0为中心的正态分布,即
- 设函数的运行时长为一常数
,则测量值
,则
2.问题转化 :
由基本假设得,
则取 ,则
,即
也服从正态分布
显然,的观测值
3.假设检验:
这里仍然采用单侧检验,原理同方法一,不妨假设比
快。
则对于显著性水平:
- 原假设:
不比
快,即
- 备择假设:
比
快,即
此时,检验就变成了对一个单正态总体均值的检验。
取检验统计量 ,其中
为
的样本标准差
则
拒绝域为
同理,只要求出这个
和t分布的分位点值,就可以做出定性结论。
四、两种方法的比较
比较程序源代码同见附件
基本原理是,通过人为制造两个快慢不同的函数,然后分别用两种方法进行验证。
万次测验结果如下:
test time: 10000
test 10000 times
method1: 9620 right
method2: 8071 right
可见方法一准确率在96%左右,方法二在80%左右,方法一更可靠一点。
五、附:
我已经按照上文的思路写好了一整套完全基于标准库的源程序,姑且称之为库,这个库从最基础的高精度函数计时到最后结果报告的打印,全部已经写好代码,既是自用,也是拿出来分享,详细内容见GitHub库的主页:
下面是一次测试以及打印效果示例:
#include "timing.h"
void foo1()
{
int a = 0;
for (int i = 0; i < 10000; ++i)
{
a += i;
}
}
void foo2()
{
int a = 0;
for (int i = 0; i < 11000; ++i)
{
a += i;
}
}
int main()
{
auto_compare(foo1, foo2);
}
效果如下:
+-------------- Comparision Report -------------+
| |
| Sample Records: |
| index f1(002515DC) f2(002515E1) |
| 0 1.7869e-05 1.93277e-05 |
| 1 1.7869e-05 1.93277e-05 |
| 2 1.7869e-05 1.93277e-05 |
| 3 1.85983e-05 1.8963e-05 |
| 4 1.75043e-05 1.93277e-05 |
| |
+-----------------------------------------------+
| |
| Analysis: |
| mean: 1.79419e-05 1.92547e-05 |
| vari: 1.59584e-13 2.65973e-14 |
| socm: 1.27667e-13 2.12778e-14 |
| ival(0.95): |
| [1.87249e-05, [1.95744e-05, |
| 1.71589e-05] 1.89351e-05] |
| |
+-----------------------------------------------+
| |
| Significance Level : 0.05 |
| Faster By: 7.317% |
| Time Saved: -6.818% |
| Conclusion: |
| ****************************** |
| * f1 is significantly faster * |
| ****************************** |
| |
+-----------------------------------------------+
| |
| Method II : |
| ****************************** |
| * f1 is significantly faster * |
| ****************************** |
| |
+-----------------------------------------------+
7319

被折叠的 条评论
为什么被折叠?



