簡體   English   中英

使用for循環的矩陣乘法會降低性能嗎?

[英]Will matrix multiplication using for loops decrease performance?

目前,我正在開發一個使用矩陣的程序。 我想出了這個嵌套循環將兩個矩陣相乘:

// The matrices are 1-dimensional arrays
for (int i = 0; i < 4; i++)
    for (int j = 0; j < 4; j++)
        for (int k = 0; k < 4; k++)
            result[i * 4 + j] += M1[i * 4 + k] * M2[k * 4 + j];

循環有效。 我的問題是:與像這樣手動將其全部寫入相比,此循環會更慢:

result[0] = M1[0]*M2[0] + M1[1]*M2[4] + M1[2]*M2[8] + M1[3]*M2[12];
result[1] = M1[0]*M2[1] + M1[1]*M2[5] + M1[2]*M2[9] + M1[4]*M2[13];
result[2] = ... etc.

因為在嵌套循環中,將計算數組位置,而在第二種方法中,則不計算數組位置。

謝謝。

與很多事情一樣,“取決於”,但在這種情況下,我傾向於第二種擴展的形式,表現幾乎相同。 任何現代編譯器都會為您展開適當的循環,並加以照顧。

兩點也許值得提出:

  1. 第二種方法比較丑陋,更容易出錯,並且編寫/維護繁瑣。

  2. 這是“過早優化” (又稱萬惡之源)的一個很好的例子。 您知道這部分是否是瓶頸? 這真的是代碼中最密集的部分嗎? 通過如此早的優化,我們導致了點1的所有內容,如果我們沒有對代碼進行基准測試,那將是直覺。

您的編譯器可能已經這樣做了,請看一下循環展開 讓編譯器進行猜測和繁重的工作,堅持使用干凈的代碼,並一如既往地衡量您的性能。

我認為循環不會變慢。 在兩種情況下,您都以相同的方式訪問M1和M2陣列的內存,即。 如果要使“手動”版本更快,請使用標量替換並在寄存器上進行計算,例如

 double M1_0 = M1[0];
 double M2_0 = M2[0];
 result[0] = M1_0*M2_0 + ...

但您也可以在循環中使用標量替換。 如果進行阻止和循環展開,則可以執行此操作(實際上,三重循環看起來像MMM的阻止版本)。

您正在嘗試做的是通過改善局部性(即更好地使用內存層次結構和更好的局部性)來加速程序。

假設您正在Intel處理器或兼容(AMD)上運行代碼,則實際上可能要切換到匯編語言來進行繁重的矩陣計算。 幸運的是,您擁有Intel-IPP庫,該庫使用高級處理器技術為您完成實際工作,並根據您的處理器選擇最快的算法。

IPP包含您可能需要的所有必要的矩陣計算。 您可能遇到的唯一問題是創建矩陣的順序。 您可能需要重新組織訂單,以便更輕松地使用要使用的IPP功能。

請注意,關於您的兩個代碼示例,第二個將更快,因為避免了+=運算符,這是一個讀/修改/寫周期,並且通常很慢(不僅如此,它要求結果矩陣全為零)首先,而第二個示例不需要先清除輸出),盡管您的矩陣很可能適合緩存...但是,處理器經過了優化,可以按順序讀取輸入數據(a [0],a 1 , a [2],a [3],...),並按順序寫回該數據。 如果您可以將算法寫得盡可能接近這樣的序列,那就更好了。 別誤會,我知道矩陣乘法不能按順序進行。 但是,如果您認為這樣做可以優化,您將獲得更好的結果(例如,將矩陣保存在內存中的順序更改可能是其中之一)。

暫無
暫無

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

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