MATLAB矩阵元素乘法优化

时间:2016-05-04 14:23:15

标签: arrays algorithm performance matlab matrix

我必须优化一段MATLAB代码。代码很简单,但它是计算单元的一部分,它称之为~8000次(没有冗余)(在实际情况下,该计算单位使用~10-20K次)。整个MATLAB代码非常冗长和复杂(对于像我这样的物理学家),但MATLAB探测器声称以下部分负责将近一半的运行时间(!)。

代码实质上是将3个矩阵(A,B,C)的3个矩阵的每个排列元素相乘,并将其与一些加权相加。 A组有一个矩阵,B组有4个矩阵,C组有7个。

我尝试了一些矢量化技术*但最多只能获得相同的运行时间。

使用MATLAB探查器我检查了每一行所花费的总时间(对于所有8000次呼叫) - 我在评论中写了这些。

for idx_b = 1:4

B_MAT=B_Container_Cell{idx_b};

for idx_c = 1:7

    C_MAT = C_Container_Cell{idx_b}(:,:,idx_c); % 60 sec

    ACB=A_MAT.*C_MAT.*B_MAT; % 20 sec

    Coeff_x = Coeff_x_Cell{idx_b}(p1,p2,idx_c,p3);
    Coeff_y = Coeff_y_Cell{idx_b}(p1,p2,idx_c,p3);
    Coeff_z = Coeff_z_Cell{idx_b}(p1,p2,idx_c,p3);

    Sum_x = Sum_x+Coeff_x.*ACB; % 15 sec
    Sum_y = Sum_y+Coeff_y.*ACB; % 15 sec
    Sum_z = Sum_z+Coeff_z.*ACB; % 15 sec

end

一些先验知识 -
A_MAT是1024x1024复数双常数矩阵,定义为循环
B_MAT是1024x1024双矩阵,基本上是稀疏的(只有0和1值,其中约为总元素的5%)
C_MAT是1024x1024复数双

Sum_x / Sum_y / Sum_z已正确启动
Coeff_X / Coeff_y / Coeff_z是双重标量 p1,p2,p3是参数(此代码段的常量)

有人知道为什么最消耗的操作是变量赋值吗? (我试图跳过作业并直接用它的表达替换C_MAT,但它会使性能恶化)

矢量化尝试
我尝试过的技术是使用cat,reshape和repmat来创建3个巨大的2D矩阵,逐个元素地将它们相乘然后将所有这些相互叠加(重新形成)并通过相关维度求和。第一个矩阵是A重复4 * 7 = 28次,第二个是重复7次的4 B矩阵,第三个矩阵是所有C矩阵跨越(= 28个矩阵)。

示例输入
以下link上的代码生成示例输入文件。这些变量(在我的计算机上)的运行时间是~0.38秒(原始代码+变量~0.42,我认为差异是因为真正的C Cell容器非常大,所以提取需要更多时间)

1 个答案:

答案 0 :(得分:2)

鉴于输入单元阵列中的数组大小相同,将输入存储为多维数组而不是单元数组可能更好,以利用MATLAB的矢量化技术,其中case为indexing用于提取特定元素,matrix-multiplication用于求和。因此,在形成输入时,我们可以寻找形成与输入相对应的多维数组:B_Container_CellC_Container_CellCoeff_x_CellCoeff_y_CellCoeff_z_Cell 。现在,这些是1D个单元格数组B_Container_Cell包含2D数组,其余数组3D。因此,当使用多维数组时,我们将它们作为一个额外的维度,即它们分别是3D4D数组。

要模拟它们的多维数组格式,让我们使用cat沿着last+1维度转换给定的单元格数组,如下所示 -

Bm = cat(3,B_Container_Cell{:});
Cm = cat(4,C_Container_Cell{:});

Cx = cat(4,Coeff_x_Cell{:});
Cy = cat(4,Coeff_y_Cell{:});
Cz = cat(4,Coeff_z_Cell{:});

最后,矢量化解决方案使用这些多维数组并获得所需的输出 -

%// Get ACB across all iterations and reshaped into (Nx28) shaped array
Ar = reshape(bsxfun(@times,bsxfun(@times,Cm,permute(Bm,[1,2,4,3])),A_MAT),[],28);

%// Use matrix-multiplication to sum reduce sliced versions of Cx, Cy and
%// Cz, to get respectived summed outputs
sz = size(A_MAT); %// Output array size
Sum_x_out = reshape(Ar*reshape(Cx(p1,p2,:,:),[],1),sz);
Sum_y_out = reshape(Ar*reshape(Cy(p1,p2,:,:),[],1),sz);
Sum_z_out = reshape(Ar*reshape(Cz(p1,p2,:,:),[],1),sz);

请注意,它看起来并非使用参数p3

运行时测试结果(针对列出的样本输入) -

--------------------------------- With Original Approach
Elapsed time is 2.412417 seconds.
--------------------------------- With Proposed Approach
Elapsed time is 1.572035 seconds.
相关问题