簡體   English   中英

MATLAB矩陣元素乘法優化

[英]MATLAB matrix element wise multiplication optimization

我必須優化一段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個矩陣)。


樣本輸入
以下鏈接上的代碼生成示例輸入文件。 這些變量(在我的電腦上)的運行時間是~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.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM