gpt4 book ai didi

arrays - MATLAB 矩阵元素明智乘法优化

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:16:55 25 4
gpt4 key购买 nike

我必须优化一段 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 矩阵,将它们逐元素相乘,然后将它们全部叠加(通过 reshape )并通过相关维度求和。第一个矩阵是A重复4*7=28次,第二个是4个B矩阵重复7次,第三个是所有C矩阵spanning(=28个矩阵)。


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

最佳答案

鉴于输入元胞数组中的数组大小相同,将输入存储为多维数组而不是元胞数组可能是更好的主意,以利用 MATLAB 的矢量化技术,在本例中为 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.

关于arrays - MATLAB 矩阵元素明智乘法优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37030592/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com