[英]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_Cell
, C_Container_Cell
, Coeff_x_Cell
, Coeff_y_Cell
和Coeff_z_Cell
。 現在,這些是1D
單元陣列,其中B_Container_Cell
包含2D
陣列,其余具有3D
陣列。 因此,當使用多維數組時,我們將它們作為一個附加維度,即它們分別是3D
和4D
數組。
為了模擬它們的多維數組格式,讓我們使用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.