如何更有效地执行此数组切片和乘法运算?

时间:2014-08-22 21:44:37

标签: performance matlab matrix multiplication

我使用此3D矩阵的最后两个维度作为2D矩阵。所以我只想将Matrix1(i,:,:)i - by - i)的结果与矢量Matrix2(i,:).')1 - 的结果相乘 - 由 - i

我能做到的唯一方法是使用一个辅助矩阵,从3D矩阵中拾取2维中的所有数字:

matrixAux(:,:) = Matrix1(1,:,:)

然后我做了乘法:

matrixAux * (Matrix2(i,:).')

它有效。但是,这很慢,因为我需要将所有3D矩阵复制到很多辅助矩阵中,我需要加速我的代码,因为我多次进行相同的操作。

如何更有效地完成这项工作,而无需复制矩阵?

1 个答案:

答案 0 :(得分:0)

方法I:bsxfun乘法

一种方法是将bsxfun的输出与@times一起使用,您可以使用其值而不是在循环中计算矩阵乘法结果 -

sum(bsxfun(@times,Matrix1,permute(Matrix2,[1 3 2])),3).'

示例

例如,我们假设Matrix1Matrix2定义如下 -

nrows = 3;
p = 6;
ncols = 2;

Matrix1 = rand(nrows,ncols,p)
Matrix2 = rand(nrows,p)

然后,你有这样的循环 -

for i = 1:size(Matrix1,1)
    matrixAux(:,:) = Matrix1(i,:,:);
    matrix_mult1 = matrixAux * (Matrix2(i,:).') %//'
end

因此,您可以直接计算矩阵乘法结果 - 而不是循环 -

matrix_mult2 = sum(bsxfun(@times,Matrix1,permute(Matrix2,[1 3 2])),3).'

因此,matrix_mult2的每一列在循环的每次迭代中都代表matrix_mult1,因为代码的输出会使它更清晰 -

matrix_mult1 =
    0.7693
    0.8690
matrix_mult1 =
    1.0649
    1.2574
matrix_mult1 =
    1.2949
    0.6222
matrix_mult2 =
    0.7693    1.0649    1.2949
    0.8690    1.2574    0.6222

方法II:"完整"矩阵乘法

现在,这一定是令人兴奋的!那么你也可以利用MATLAB的快速矩阵乘法来再次获得中间矩阵乘法结果而不需要循环。如果Matrix1nrows x p x ncols,您可以将其重新整形为nrows*p x ncols,然后将其与Matrix2进行矩阵乘法运算。然后,要获得等效的matrix_mult2,您需要从乘法结果中选择索引。这正是在这里实现的 -

%// Get size of Matrix1 to be used regularly inside the codes later on
[m1,n1,p1] = size(Matrix1);

%// Convert 3D Matrix1 to 2D and thus perform "full" matrix multiplication 
fmult = reshape(Matrix1,m1*n1,p1)*Matrix2'; %//'

%// Get valid indices
ind = bsxfun(@plus,[1:m1:size(fmult,1)]',[0:nrows-1]*(size(fmult,1)+1)); %//'

%// Get values from the full matrix multiplication result
matrix_mult3 = fmult(ind); 

此处,matrix_mult3必须与matrix_mult2相同。

观察:由于我们没有使用从全矩阵乘法计算的所有值,而是将其索引到其中并选择其中的一些元素,因此这种方法在某些方面的性能优于其他方法情况。当nrows是一个较小的值时,这种方法似乎是最好的方法,因为在这种情况下我们将使用来自全矩阵乘法输出的更多元素。


基准测试结果

针对这三种方法测试了两个案例,测试结果似乎支持我们之前讨论过的假设。

案例1

Matrix 1400 x 400 x 400,运行时为 -

--------------- With Loops
Elapsed time is 2.253536 seconds.
--------------- With BSXFUN
Elapsed time is 0.910104 seconds.
--------------- With Full Matrix Multiplication
Elapsed time is 4.361342 seconds.

案例2

Matrix 140 x 2000 x 2000,运行时为 -

--------------- With Loops
Elapsed time is 5.402487 seconds.
--------------- With BSXFUN
Elapsed time is 2.585860 seconds.
--------------- With Full Matrix Multiplication
Elapsed time is 1.516682 seconds.