1. 简介
在性能优化过程中,我们常常需要衡量新版本代码相较于旧版本的提升程度。本文将介绍如何以运行时间为指标来计算百分比提升。例如,当我们优化代码使其运行更快时,就可以使用这些方法来量化优化效果。
与对算法复杂度进行理论分析(如时间与空间复杂度)相比,这种经验性的方法是有力的补充。特别是当代码过于复杂而难以进行数学分析时,这种实测方式就是唯一可行的选择。当然,如果我们要用统计数据来支撑结论,还需考虑多次运行和任务多样性等因素。
2. 什么是运行时间的提升?
假设:
t_old
表示旧版本完成某项任务所花的时间t_new
表示新版本完成相同任务所花的时间
我们的目标是用百分比来表达 t_new
相较于 t_old
的提升程度。
⚠️ 注意:时间越短越好,但人们通常认为“数值小”代表性能差。因此,我们需要一个能反映“时间越短,提升越大”的指标。
此外,我们希望用相对值而非绝对值来表达提升。例如,从1000秒减少到900秒(减少100秒)和从200秒减少到100秒(同样减少100秒),虽然绝对值相同,但后者提升更显著。百分比能更好地体现这种差异。
目前主流有两种方式来定义这种百分比提升。
3. 提升 = 节省的时间比例
这是最直观的一种方式:
我们先计算时间差,再除以旧版本的执行时间:
$$ \text{Improvement} = \frac{t_{old} - t_{new}}{t_{old}} = 1 - \frac{t_{new}}{t_{old}} \quad (\text{结果乘以100%}) $$
✅ 优点:直观,易于理解
❌ 缺点:当 t_new > t_old
时会得到负数,不够直观
3.1 示例
假设旧版本训练模型用了300秒,新版本优化后用了30秒:
$$ \frac{300 - 30}{300} = \frac{270}{300} = 0.9 = 90% $$
这表示我们节省了90%的时间。
4. 提升 = 单位时间内完成的任务量
另一种方式是从“效率”角度出发:在旧版本完成1个任务的时间内,新版本能完成多少个任务?
计算方式如下:
$$ \text{Improvement} = \frac{t_{old}}{t_{new}} \quad (\text{结果乘以100%}) $$
✅ 优点:更强调“单位时间产出”,适合评估吞吐量提升
❌ 缺点:当 t_new > t_old
时结果小于100%,不够直观
4.1 示例
继续使用上面的例子:
$$ \frac{300}{30} = 10 = 1000% $$
这表示在旧版本完成1个任务的时间内,新版本可以完成10个任务。
4.2 变体形式
还有一种变体是:
$$ \frac{t_{old}}{t_{new}} - 1 $$
这样表示的是“新版本比旧版本多完成的任务比例”。例如上面的例子:
$$ \frac{300}{30} - 1 = 10 - 1 = 9 = 900% $$
即新版本多完成了900%的任务量。
⚠️ 但同样地,当 t_new > t_old
时会得到负数,需谨慎解读。
5. 提升的统计评估
在实际工程中,不能仅凭单次运行就判断性能优劣。因为运行时间可能受环境干扰(如CPU负载、GC触发等)或任务本身特性影响。
要科学评估性能提升,应该:
- 在多个任务(unit)上重复运行
- 多次测试(run)
- 分析时间分布
5.1 实验设置
假设我们有:
m
个任务(unit)- 每个任务运行
n
次(run)
那么我们有两个 m x n
的运行时间矩阵:
t_old[i][j]
:旧版本在第i
个任务的第j
次运行时间t_new[i][j]
:新版本在第i
个任务的第j
次运行时间
我们可以用前面提到的任意一种公式(如公式1或公式2)来计算每次运行的提升值。
5.2 匹配运行(Matched Runs)
如果我们能确保每次运行的条件一致(如相同的CPU负载、相同的随机种子),那么我们可以直接对 t_new[i][j]
和 t_old[i][j]
进行一一比较。
提升值计算如下:
$$ \text{AvgImprovement} = \frac{1}{mn} \sum_{i=1}^{m} \sum_{j=1}^{n} IMP(t_{new,i,j}, t_{old,i,j}) $$
其中 IMP(...)
是我们前面定义的任意一种提升公式。
建议配合直方图或箱线图展示分布,以增强说服力。
5.3 非匹配运行(Unmatched Runs)
如果我们无法确保运行条件一致,就不能简单地一一对应。此时可以进行所有可能的配对比较:
$$ \text{AvgImprovement} = \frac{1}{mn^2} \sum_{i=1}^{m} \sum_{j_1=1}^{n} \sum_{j_2=1}^{n} IMP(t_{new,i,j_1}, t_{old,i,j_2}) $$
这样可以更全面地评估提升效果,但计算量更大。
5.4 示例
假设有3个任务,每个任务运行4次,数据如下:
t_old = [
[105, 105, 97, 105],
[97, 96, 98, 100],
[104, 108, 98, 104]
]
t_new = [
[72, 70, 71, 68],
[72, 66, 75, 78],
[75, 73, 71, 66]
]
使用公式(2)计算平均提升:
$$ \frac{1}{12} \left( \frac{105}{72} + \frac{105}{70} + \cdots + \frac{104}{66} \right) \approx 1.42 = 142% $$
结论:新版本在旧版本完成1个任务的时间内,平均可以完成1.42个任务。
5.5 统计检验
我们还可以进一步做统计检验,比如:
- 计算有多少次运行的提升率超过100%
- 构建置信区间判断新版本是否显著优于旧版本
这样可以排除偶然性,增强结论的可信度。
6. 总结
本文介绍了两种常用的计算运行时间百分比提升的方法:
- 节省时间比例法:反映时间减少的比例
- 单位时间任务量法:反映单位时间内完成的任务倍数
此外,我们还讨论了在实际工程中如何通过多次运行和统计分析来科学评估性能提升。
✅ 建议:
- 多次运行 + 多个任务 + 统计分析 = 更可靠
- 优先使用公式2(任务量法),因为它更能体现效率提升
- 避免仅凭单次运行得出结论,谨防“踩坑”