我开发了一种图像特征提取算法。为了评估算法提取时间,我运行了开发的方法及其竞争对手,使用一组图像作为输入。所有提取算法都是在Matlab中实现的。
然而,有人向我指出,使用 Matlab 实现的时间比较是值得怀疑的。这种说法有什么根据吗?
这个论点有两个可能的原因:时序测量可能存在可变性,并且 Matlab 据说很慢,因此计时毫无意义。
对于第一个原因,获得准确的时间确实是一个挑战,特别是如果程序之间的运行时间非常相似。因此,简单的tic
和toc
应替换为timeit函数。
第二个原因是假的。当然,在 Matlab 中执行某些操作可能需要更长的时间,但 TheMathWorks 在过去几年中花费了大量精力来使 Matlab 更快,因此在 C/C++ 中重新实现算法实际上会使它变慢。的确,算法的相对速度可以在语言之间发生变化,如果其中一种算法更适合语言的优势。但是,用同一种语言实现这两种算法,并诚实地努力以有效的方式实现算法,肯定会带来公平的比较。
时间的有效性取决于您如何实现算法以及如何在"现实世界"中使用它们。 如果你有一个算法的应用程序,它将用 Matlab 实现,那么你的时序没有错,因为你正在计时算法的使用方式。 但是,如果您计划使用较低级别的语言(如C++)重新编码算法,则可能会得到明显不同的结果。
Mathworks花了很多时间来优化Matlab中的工具箱和基本操作,所以像矩阵乘法,矩阵逆,FFT,SVD等通常与一个好的C++实现一样快。 您不一定知道优化了哪些工具箱例程。 如果您的算法仅依赖于高度优化的例程,而竞争算法依赖于不太优化的例程,则您的算法可能看起来更好,仅仅是因为底层实现更好。
可能存在差异的另一个原因是 Matlab 是一种解释型语言。 当你的程序有一个循环时,解释器必须弄清楚代码每次通过循环在做什么。 相比之下,矩阵操作已提前编译为机器代码,并且没有解释器开销。 例如,如果我运行:
start = time;
x = zeros(1000,1000);
x = x+1;
stop = time;
stop - start
在我的计算机上,我得到 0.02297 秒。 如果我使用循环运行等效版本:
start = time;
x=zeros(1000,1000);
for i = 1:1000
for j = 1:1000;
x(i,j) = x(i,j) + 1;
end;
end;
stop = time;
stop - start
我得到 18.175 秒。 (上面@Jonas提到的方法在需要高精度时提供了更好的时序,但在这种情况下,有足够的数量级差异,这个简单的方法足够好用。
如果竞争算法在循环中做了很多工作,而你的算法更依赖于内置函数,那么你的算法可能会击败竞争对手,因为它的解释器开销更少。
如果你打算只在 Matlab 内部使用这些算法,并且无法从竞争对手那里消除解释器开销,那么声称你的算法更好是有效的——至少对于 Matlab 实现是这样。 如果你想要求一个更一般的结果,至少你必须证明解释器不是性能差异的原因。 用像C++这样的语言实现所有算法可以消除解释器的开销。 为了进行公平的比较,您必须确保已经完成了所有底层算法的快速实现(例如,FFT,SVD,矩阵乘法)。 幸运的是,优化的库可用于许多不同语言的许多常见算法。
当然,如果你能证明你的算法的渐近复杂度更好(O()表示法),这将表明它在更广泛的实现中可能更好,尽管常量在实际实现中很重要。