performance - 如何在 Octave 中对方法进行基准测试?
问题描述
Matlab 有timeit方法,有助于比较一个实现与另一个实现的性能。我在八度音阶中找不到类似的东西。我编写了这个基准方法,运行函数 f N 次,然后返回所用的总时间。这是比较不同实现的合理方法还是我错过了“热身”之类的关键内容?
function elapsed_time_in_seconds = benchmark(f, N)
% benchmark runs the function 'f' N times and returns the elapsed time in seconds.
timeid = tic;
for i=1:N
output = f();
end
elapsed_time_in_seconds = toc(timeid);
end
解决方案
MATLABtimeit
执行以下操作(您可以阅读整个函数,它是一个 M 文件):
- 粗略估计
t_rough
调用函数的时间f
。 - 使用估计来确定
N
大约N*t_rough
0.001 秒。 - 确定
M
不M*N*t_rough
超过 15 秒,但M
必须在 3 到 11 之间。 - 循环
M
次数: - 通话
f()
N
次数并记录总时间。 - 确定
M
时间的中位数,除以N
。
两个循环M
和的目的N
如下: 调用f()
N
times 确保tic
/测量的时间toc
足够大以至于可靠,该循环避免尝试对太短以至于无法计时的时间进行计时。重复测量M
时间并保持中间值试图使测量对系统上发生的其他事情造成的延迟具有鲁棒性,这可能会人为地夸大记录的时间。
该函数通过其句柄减去调用函数的开销(通过对空函数的调用计时来确定),以及tic
/toc
调用时间(也通过实验确定)。它没有减去内循环的成本,大概是因为在 MATLAB 中它是由 JIT 优化的,它的成本可以忽略不计。
还有一些进一步的改进。确定的函数t_rough
首先预热tic
并toc
通过调用每个函数两次,然后使用while
循环确保它调用f()
至少 0.001 秒。但是在这个循环中,如果第一次迭代至少需要 3 秒,那么它只是将那个时间作为粗略估计。如果第一次迭代花费的时间较少,则丢弃第一次计数(预热),然后使用所有后续调用的中值作为时间的粗略估计。
f()
使用正确数量的输出参数调用函数也付出了很多努力。
代码中有很多注释解释了所有这些步骤背后的原因,值得一读。
作为最低限度,我会增加你的基准功能如下:
function elapsed_time_in_seconds = benchmark(f, N, M)
% benchmark runs the function 'f' N*M times and returns the elapsed time in seconds.
tic; [~] = toc; tic; [~] = toc; % warmup
output = f(); % warmup
t = zeros(M, 1);
for k=1:M
timeid = tic;
for i=1:N
output = f();
end
t(k) = toc(timeid) / N;
end
elapsed_time_in_seconds = median(t);
end
如果您使用该函数直接比较各种替代方案,保持N
和恒定,M
那么函数调用和循环的开销是无关紧要的。tic
toc
此函数确实假设f
具有一个输出参数,但不一定如此。您可以只调用f()
而不是output = f()
,这将适用于有或没有输出参数的函数。但是,如果函数需要一定数量的输出才能正常工作,或者触发您想要计时的计算,那么您必须调整函数以使用正确数量的输出参数调用它。
您可以想出一些启发式来确定M
from N
,这将使使用此函数更容易一些。
推荐阅读
- r - pivot_wider() 参数意味着不同的行数 Eroor
- php - LIBXML_NOBLANKS 究竟做了什么?
- java - 如何使用 WriteBatch 删除列表中的项目?
- blender - 在编辑模式下显示顶点/边时隐藏网格面(Blender 2.8)
- python - GEKKO 错误:在约束和目标内调用函数时出现“没有等式 (=) 或不等式 (>,<) 的方程”
- exception - Symfony 4 - 抛出错误 500 而不是 403
- amazon-web-services - 通过未签名的 POST 到 REST API 调用 AWS Lambda
- php - 我想使用 PHP 删除两个数组中的公共元素
- database - Rust - 我可以让这个柴油 dsl::find() 函数更通用吗?
- java - Java表问题与获取列的平均值