无心人 发表于 2008-5-8 21:36:01

时间测试的艺术

测试函数效率的时候如果做的好,得到的结论就正确,如果测试的方法不对,那么就很容易得到错误的甚至相反的结论
1、尽量使用高精度的计时手段,这个网上文档里有很深入的讨论,大家都可以找到,本论坛几个热门的测试问题示例代码更是可以做参考。使用高精度计时器,得到的时间精确度越大,则最终测试到的函数执行周期就越精确,这里需要注意的是,高精度计时也是有最小时间单位的,尽量保证你测量的时间是最小时间单位的1000倍甚至更多,否则,因为计时误差,很可能你得到的时间的有效位数不是很大,会影响你的结果的精确度。
2、选择合适的问题规模,比如高精度加法你每次测量32个双字的加法,即使循环测量100万次,因为每次都存在函数调用时间,而加法时间和函数调用时间相比可能差别不大,而函数调用的时间在CPU指令周期上是有起伏的,造成每次完成函数的时间都存在差异而且函数调用的比例很高,反而功能指令的时间却不多,使得精确测量功能代码的意图落空,解决的途径是加大测试尺度,比如测试1024双字设置更多。
3、如果问题的规模很小,那么就需要增大测量次数使得总执行时间至少在0.01秒以上,以避免测试时间不准确。同时还要采取特殊措施,比如大家曾讨论过的32位数位索引的算法,每次函数调用都是100个CPU时钟周期左右的时间,那么这里我们就要尽量采取fastcall调用形式,且使函数体尽量减少内存访问,以使对环境的依赖最小,甚至我们还可能要写个空壳函数与正常函数执行相同的次数,分别测试两种情况的时间信息,相减得到实际执行时间。
4、如果函数不允许执行多次,而且执行周期距比可测量的高精度最小时间单位小,则就可以采取使用RDTSC等CPU内部提供的测试手段来测试CPU执行指令周期数来比较时间消耗,但因为环境的多线程,抢占多任务等特性,这种方式的测量受测试环境的影响很大,可采取多次测量取平均的方式得到最接近实际的结果。
5、测试数据的处理,考虑每次测试的数据受环境的影响很大,可以考虑多进行几次测试取平均值,另外最后的结果不必保留很多位数,一般4位就足够了,因为原始数据精度虽然高,但受环境影响,起伏是很大的!另外如果是经过处理的数据,请注意选择单位,以避免多余的零。

liangbch 发表于 2008-5-8 22:07:10

 我在我的CSDN博客上有一篇讨论计时的文章阶乘之计算从入门到精通-程序运行时间的测量,该文详细讨论了3种不同精度的计时函数或者指令的(GetTickCount, QueryPerformanceCounter和RDTSC)用法,并给出代码。

无心人 发表于 2008-5-8 22:14:24

:)

俺只讲原则
不讲方法
方法有的是

无心人 发表于 2008-5-8 22:15:23

:lol

你赶快给我改你帖子去
你上面0我给改了两个帖子
剩下一个自己改

liangbch 发表于 2008-5-8 23:04:00

当然,测试方法很重要,实际上,函数的运行时间并非像GMP所说的那样,每个循环步有固定的时钟周期。时间有一定的随意性,每次测试都不相同,为此,测试应遵循3条原则。
1.被调函数的参数要有适当的规模,比如对1024个DWORD相加 应该比对16个DWORD相加,更具代表性。
2.多次调用同一函数,求总的运行时间,因为只调用一次或者几次,时间花费太少,可能不易度量。
3.多次测试,取其最小值,一般可去测试3次以上,取其最小值。我的那个 B计划之基本函数性能预览 中对大数加,减,求补采用的是测试8次,取其最小值。

无心人 发表于 2008-5-9 08:09:21

误差存在于以下两个方面
1、调用所在进程的CPU时钟片用完被切换到其他进程任务,系统中断消耗等。
2、调用函数的CPU指令call本身存在长的CPU时钟消耗,甚至有时超过函数体本身指令消耗,且如果调用系统调用,还存在进程切换、用户级到核心级的转换甚至中断消耗。

所以俺感觉找位索引的那个问题,最终时间远大于32个时钟,很不好解释。

pphu 发表于 2011-12-14 12:29:09

多线程下clock和gettimeofday都失效了,郁闷
页: [1]
查看完整版本: 时间测试的艺术