理论上,您提出的两种方法之间不应该存在性能差异,因为if
无论如何,每次循环都必须评估语句,但让我们仔细看看一些分析(timeit
)。我在 R2014a 到 R2015b 版本上进行了一些测试。
对于每个测试,我创建一个数组p
具有不同大小的相同数量的 1 和 0,并且随机化 0 和 1 的顺序。
%// Creates random zeros and ones of size n
p = mod(randperm(n),2);
对于第一次测试,我禁用 JIT 编译器 http://www.mathworks.com/matlabcentral/fileexchange/18510-matlab-performance-measurement/content/Documents/MATLABperformance/configinfo.m feature('JIT', 'off')
第二个测试我启用了 JIT 编译器feature('JIT', 'on')
.
我用于所有版本 MATLAB 的脚本是:
function tests()
V = ver;
sz = round(linspace(100, 10000,100));
hfig = figure('Position', [0 0 900 400]);
%// Disable JIT
feature('JIT', 'off')
runtests(sz, 1, ['JIT Disabled ', V(1).Release]);
%// Enable JIT
feature('JIT', 'on')
runtests(sz, 2, ['JIT Enabled ', V(1).Release]);
%// Match up ylims on all plots
ax = findall(hfig, 'type', 'axes');
ylims = get(ax, 'ylim');
ylims = cat(1, ylims{:});
set(ax, 'ylim', [0, max(ylims(:,2))])
end
function out = runtests(sz, n, label)
times1 = zeros(numel(sz), 1);
times2 = zeros(numel(sz), 1);
for k = 1:numel(sz)
p = mod(randperm(sz(k)),2);
times1(k) = timeit(@()continueit(p));
p = mod(randperm(sz(k)),2);
times2(k) = timeit(@()ifit(p));
end
subplot(1,2,n)
plots(sz, cat(2, times1, times2))
title(label)
end
function plots(sz, times)
plot(sz, times * 1000)
legend({'Continue', 'If'})
xlabel('Size of Array')
ylabel('Execution Time (ms)')
end
function continueit(p)
c = 1;
for k = 1:numel(p)
if p(k) ~= 1
continue;
end
c = c * k;
end
end
function ifit(p)
c = 1;
for k = 1:numel(p)
if p(k) == 1
c = c * k;
end
end
end
R2014a
正如你在这里看到的,continue
和if
声明有very在未打开 JIT 加速的情况下,性能类似。但是,当您打开加速(MATLAB 的默认设置)时,only the if
声明似乎正在加速。的速度continue
方法保持相对不变。结果,if
语句会执行得更快。
这可能是由于 JIT 编译器加速了执行的指令块连续多次。通过将分支逻辑与continue
在那里,您根据条件更改程序的流程,这会更改每次循环运行的指令。这显然会阻止 JIT 编译。
R2014b
与 R2014a 类似。
R2015a
与 R2014a 类似。
R2015b (新的执行引擎 http://www.mathworks.com/products/matlab/matlab-execution-engine/介绍)
不幸的是,在 R2015b 中,您似乎无法以相同的方式禁用 JIT(如果有人知道如何,请告诉我,我会更新),因此这两个图都启用了加速,但似乎新的执行引擎消除 JIT 编译器先前创建的执行时间差异。这是因为新的执行引擎能够进行JIT编译all代码(显然包括continue
)
来自 MATLAB 文档:
所有 MATLAB 代码的即时编译
重新设计的 MATLAB 执行引擎对所有 MATLAB 代码使用 JIT 编译,而之前的执行引擎在某些情况下使用 JIT 编译。 JIT 编译生成本机机器级代码,该代码针对正在执行的 MATLAB 代码和特定硬件平台进行了优化。
当 MATLAB 代码被额外执行多次并且可以重用已编译的代码时,JIT 编译的性能优势最大。这种情况发生在常见情况下,例如 for 循环,或者当应用程序在 MATLAB 会话中额外运行多次且至少部分应用程序的 MATLAB 文件在后续运行之间保持不变时。
Summary
在旧版本的 MATLAB(R2015a 及更早版本)中,continue
语句阻止了 JIT 加速,导致if
启用 JIT 时(默认情况下)执行速度更快的版本。随着R2015b中新执行引擎的引入,all代码是 JIT 加速的,因此,差异实际上已经消失。
正如您所指出的,if
声明只是barely还更快。这可能是由于以下开销造成的actually呼叫continue
。从总体来看,这种差异可以忽略不计。此外,如果 for 循环的整体性能really取决于这种差异,这意味着速度contents循环的速度非常快,你的瓶颈是for
循环本身,你应该考虑向量化你的代码(即,如果我放一个magic(3)
在我的内心呼唤for
循环而不是这里显示的简单乘法,差异完全消失)。