这是我的基准测试,比较了@TobiasKienzler回答中提到的方法。我正在使用TIMEIT功能来获得更准确的时间。
function [t,v] = matrixMultTest()
n = 2; m = 2; p = 1e5;
A = rand(n,m,p);
B = rand(m,n,p);
%# time functions
t = zeros(5,1);
t(1) = timeit( @() func1(A,B,n,m,p) );
t(2) = timeit( @() func2(A,B,n,m,p) );
t(3) = timeit( @() func3(A,B,n,m,p) );
t(4) = timeit( @() func4(A,B,n,m,p) );
t(5) = timeit( @() func5(A,B,n,m,p) );
%# check the results
v = cell(5,1);
v{1} = func1(A,B,n,m,p);
v{2} = func2(A,B,n,m,p);
v{3} = func3(A,B,n,m,p);
v{4} = func4(A,B,n,m,p);
v{5} = func5(A,B,n,m,p);
assert( isequal(v{:}) )
end
%# simple FOR-loop
function C = func1(A,B,n,m,p)
C = zeros(n,n,p);
for k=1:p
C(:,:,k) = A(:,:,k) * B(:,:,k);
end
end
%# ARRAYFUN
function C = func2(A,B,n,m,p)
C = arrayfun(@(k) A(:,:,k)*B(:,:,k), 1:p, 'UniformOutput',false);
C = cat(3, C{:});
end
%# NUM2CELL/FOR-loop/CELL2MAT
function C = func3(A,B,n,m,p)
Ac = num2cell(A, [1 2]);
Bc = num2cell(B, [1 2]);
C = cell(1,1,p);
for k=1:p
C{k} = Ac{k} * Bc{k};
end;
C = cell2mat(C);
end
%# NUM2CELL/CELLFUN/CELL2MAT
function C = func4(A,B,n,m,p)
Ac = num2cell(A, [1 2]);
Bc = num2cell(B, [1 2]);
C = cellfun(@mtimes, Ac, Bc, 'UniformOutput', false);
C = cell2mat(C);
end
%# Loop Unrolling
function C = func5(A,B,n,m,p)
C = zeros(n,n,p);
C(1,1,:) = A(1,1,:).*B(1,1,:) + A(1,2,:).*B(2,1,:);
C(1,2,:) = A(1,1,:).*B(1,2,:) + A(1,2,:).*B(2,2,:);
C(2,1,:) = A(2,1,:).*B(1,1,:) + A(2,2,:).*B(2,1,:);
C(2,2,:) = A(2,1,:).*B(1,2,:) + A(2,2,:).*B(2,2,:);
end
结果:
>> [t,v] = matrixMultTest();
>> t
t =
0.63633 # FOR-loop
1.5902 # ARRAYFUN
1.1257 # NUM2CELL/FOR-loop/CELL2MAT
1.0759 # NUM2CELL/CELLFUN/CELL2MAT
0.05712 # Loop Unrolling
正如我在评论中解释的那样,一个简单的 FOR 循环是最好的解决方案(在最后一种情况下没有循环展开,这仅适用于这些小的 2×2 矩阵)。