刚才,我知道Matlab&Octave使用了Wikipedia中的column-major。
Column-major order is used in Fortran, OpenGL and OpenGL ES, MATLAB,
GNU Octave, R, Julia, Rasdaman, and Scilab.
所以我只是在Matlab和Octave中检查" for loop"速度。 结果如下:
Matlab的
>> x = rand(10000);
>> tic; for i=1:10000 for j=1:10000 k=x(i,j); end; end; toc; % row-major
Elapsed time is 2.320215 seconds.
>> tic; for i=1:10000 for j=1:10000 k=x(j,i); end; end; toc; % column-major
Elapsed time is 0.433013 seconds.
不出所料,列优先顺序比行优先顺序快。
八度
> x=rand(5000);
> tic; for i=1:5000 for j=1:5000 k=x(i,j); end; end; toc; % row-major
Elapsed time is 77 seconds.
> tic; for i=1:5000 for j=1:5000 k=x(j,i); end; end; toc; % column-major
Elapsed time is 78 seconds.
在两种情况下结果都是相同的。
题:
为什么行优先循环和列优先循环在Octave中执行相似的操作,尽管它使用列优先对齐方式?
这可能可以解释某些情况,尤其是Octaves缺乏JIT的情况:stackoverflow.com/questions/12569351/
我已经看到了该链接。 它给出了为什么Matlab循环比八度要快得多(10000x10000 v / s为0.5秒,八度为5000x5000为78秒)的见解,但我没有提到我的问题。
使用feature accel off再次运行测试,我发现行或列优先版本之间没有真正的区别(非常类似于您的Octave结果)。 因此,JIT编译是时间上的差异,我想非矢量化循环与JIT编译器正在使用的矢量化版本一样,并不依赖于如何访问矩阵。
哦,太酷了。 但是,为什么Matlab和Octave都没有区别呢? 我的意思是,以任何方式,按列循环都应该更快,对吗?
如果您尝试对整个列或行进行操作,则会发现有所不同。在MATLAB和Octave中尝试以下代码:
%% Columns
a = rand(n);
b = zeros(n,1);
tic
for ii = 1:n
b = b + a(:,ii);
end
t1 = toc
%% Rows:
a = rand(n);
b = zeros(1,n);
tic
for ii = 1:n
b = b + a(ii,:);
end
t2 = toc
在我的计算机上,这给出了:
%% MATLAB:
t1 = 0.0287
t2 = 0.3778
%% Octave*:
t1 = 0.089480
t2 = 0.20313
现在,八度音阶的差异不如MATLAB中的大,但在八度音阶中仍是一个显着的差异(快两倍以上)。
David已经发布了有关JIT编译的答案,因此在这里我将跳过这一部分。
*我没有Octave,所以我不得不在这里进行测试。
为了扩大我的评论,我将发布答案。我对此不是专家。
首先,在Matlab中使用feature accel off运行测试以禁用JIT编译,返回的结果与Octave的结果大致相同。因此,Matlab和Octave之间的速度提高归因于Matlab的JIT编译,该编译必须对循环进行矢量化处理。
其次,Matlab的JIT编译版本的列优先级比行优先级更快的原因是因为Matlab是列优先级的,这是有道理的。
然后,对于没有JIT编译的Octave和Matlab,列优先评估都快了一点。由于每个值都是分别从随机矩阵中提取的,因此我可以理解为什么这样做会很慢,但为什么行或列之间的差异最大呢?
希望无论如何都会有所帮助,也许其他人可以扩大/改进它或发布真实的答案!
+1作为答案。 但是我仍然不明白为什么没有JIT就没有区别。
我认为这仅仅是由于以下事实:Matlab / Octave每次循环迭代都必须去检索矩阵的单个元素,使用它进行计算,然后检索下一个元素。 它不是将矩阵的各列加载到缓存中并使用每个元素,而是在加载缓存中的单个元素,然后删除(?)它们,然后将下一个元素加载到缓存中。