介绍
我有一个算法,需要循环数十亿(万亿)次,并操作一个存储在7个维度[10x10x10x10x10x10x10]中的矩阵。我发现访问7维矩阵中的元素非常慢,因此我进行了一些测试,以确定访问多维矩阵元素的性能。
假设
我想到MatLab在幕后使用线性索引,并且我的一个朋友说性能损失可能是由于将“正常”索引转换为线性索引导致的来源。
测试方法
为了测试这个假设,我测试了2D到7D矩阵的线性索引和常规索引访问元素。我改变了我正在访问的元素以及我正在访问的矩阵大小,即每个维度的长度,但这并没有显著改变结果。我用于测试的文件如下所示。使用的硬件是Intel(R) Xeon(R) CPU E5-1620 v2 @ 3.70 GHz,16GB RAM。MatLab版本为R2013B。
结果
Normal indexing 2D: 0.073659s
Linear indexing 2D: 0.064026s
Normal indexing 3D: 0.050719s
Linear indexing 3D: 0.064096s
Normal indexing 4D: 0.055674s
Linear indexing 4D: 0.062112s
Normal indexing 5D: 15.689907s
Linear indexing 5D: 5.265076s
Normal indexing 6D: 16.660496s
Linear indexing 6D: 5.295958s
Normal indexing 7D: 17.029072s
Linear indexing 7D: 5.291139s
似乎在4D矩阵之内,普通索引与线性索引在性能方面非常相似。对于3D和4D矩阵,使用普通索引略微更可取。超过4D矩阵,线性索引比普通索引更可取,但普通索引和定期索引都会受到巨大的性能惩罚(约为两个数量级)。
结论
故事的寓意是,在追求高性能时,当运行MatLab时,仔细考虑矩阵中是否需要超过四个维度的内容(除了明显的事实,例如C ++对于大多数应用程序要快得多等等,但这可能是另一个讨论)。
问题(s)
正如标题所示:超出矩阵四个维度的原因是什么(潜在的原因),导致性能急剧下降?其他语言(例如C ++)是否也表现出这种行为?
用于测试的代码
clear all
clc
% Number if iterations
n=10000000;
A = rand(10,10);
k1=sub2ind(size(A),3,2);
fprintf('\n')
tic
for ii=1:n
A1=A(3,2);
end
a=toc;
fprintf('Normal indexing 2D: %fs\n',a)
tic
for ii=1:n
A2=A(k1);
end
a=toc;
fprintf('Linear indexing 2D: %fs\n',a)
B = rand(10,10,10);
k2=sub2ind(size(B),3,2,1);
tic
for ii=1:n
B1=B(3,2,1);
end
a=toc;
fprintf('Normal indexing 3D: %fs\n',a)
tic
for ii=1:n
B2=B(k2);
end
a=toc;
fprintf('Linear indexing 3D: %fs\n',a)
C = rand(10,10,10,10);
k3=sub2ind(size(C),3,2,1,10);
tic
for ii=1:n
C1=C(3,2,1,10);
end
a=toc;
fprintf('Normal indexing 4D: %fs\n',a)
tic
for ii=1:n
C2=C(k3);
end
a=toc;
fprintf('Linear indexing 4D: %fs\n',a)
D = rand(10,10,10,10,10);
k4=sub2ind(size(D),3,2,1,10,1);
tic
for ii=1:n
D1=D(3,2,1,10,1);
end
a=toc;
fprintf('Normal indexing 5D: %fs\n',a)
tic
for ii=1:n
D2=D(k4);
end
a=toc;
fprintf('Linear indexing 5D: %fs\n',a)
E = rand(10,10,10,10,10,10);
k5=sub2ind(size(E),3,2,1,10,1,2);
tic
for ii=1:n
E1=E(3,2,1,10,1,2);
end
a=toc;
fprintf('Normal indexing 6D: %fs\n',a)
tic
for ii=1:n
E2=E(k5);
end
a=toc;
fprintf('Linear indexing 6D: %fs\n',a)
F = rand(10,10,10,10,10,10,10);
k6=sub2ind(size(F),3,2,1,10,1,2,3);
tic
for ii=1:n
F1=F(3,2,1,10,1,2);
end
a=toc;
fprintf('Normal indexing 7D: %fs\n',a)
tic
for ii=1:n
F2=F(k6);
end
a=toc;
fprintf('Linear indexing 7D: %fs\n',a)
toc
保存到a
中! - Yvon