說明:
1.轉載請聯絡本人
2.程式碼在最後實驗目標
通過編寫OpenMp版本的矩陣乘法(SGEMM)熟悉OpenMP程式設計模型,鼓勵嘗試不同的優化策略。
問題描述
在數學領域中,矩陣乘法將兩個矩陣進行相乘,得出另一個矩陣。
矩陣乘法在實際應用中有廣泛的使用,並被不同的程式語言所實現。1979年制定的基礎線性代數子程式標準(BLAS)描述了基本的線性代數運算,包括矩陣乘法。
BLAS分為三個級別,而矩陣-矩陣運算屬於第三級。
下式中,a、b為常數,A、B、C為矩陣。
C = aAB + bC
實驗要求
- 根據記憶體大小測不同規模矩陣的處理速度(GFLOPS/s),並給出計算公式
- 請計算系統的理論峰值,如果沒有達到理論峰值,嘗試給出原因
解決思路與方法
1.實現OpenMP下的普通版本的矩陣相乘:
用OpenMP編寫兩個n階的方陣A和B的相乘程式,結果存放在方陣C中,其中乘法用for編譯製導語句實現並行化操作,並調節for編譯製導中schedule的引數,使得執行時間最短
使用num_threads()函式指定並行執行緒數
2.優化版:
1)利用矩陣分塊
將矩陣乘法的計算轉化為其各自分塊矩陣相乘而後相加,能夠有效減少乘數矩陣和被乘數矩陣調入記憶體的次數,可加快程式執行。
2)用一維陣列表示二維
二維陣列在記憶體中也是一維陣列,但是可以通過轉換的公式,減少實際的乘法次數,以達到優化效果
注:分塊和一維表示不能同時進行。
(同時進行會報錯,可能是涉及到分塊的問題,一維的位置規則和分塊的位置不太一樣)
實驗
1.實驗環境
本機: CPU:i5-4210U 記憶體:8G OS: Windows10 1607
實驗室:CPU: i7-7700K GPU:GTX 1080 記憶體:8G DDR4 OS:Ubuntu 16.04
2.結果及分析
不同規模矩陣處理速度公式:
Speed = 2*N^3/time Gflops
(對結果矩陣C分析知,每個迴圈進行一次加和乘操作)GPU理想值:單精度浮點運算運算能力是9Tflops 一個TFLOPS(teraFLOPS)等於每秒一萬億(=10^12)次的浮點運算
時間/s | 256 | 512 | 1024 | 2048 |
---|---|---|---|---|
本地 | 0.37 | 3.72 | 50.81 | / |
GPU | 0.049 | 0.47 | 3.68 | 104.3 |
GPU(時間/s) | 256 | 512 | 1024 | 2048 |
---|---|---|---|---|
分塊 | 0.046 | 0.46 | 3.75 | 29.9 |
一維陣列 | 0.019 | 0.364 | 2.91 | 82.1 |
注:每個時間是執行三次取平均值的結果(執行緒數量均為64)
P.S Max=2048下執行緒數量從64換到256,時間上沒有任何的進步……
結論
在GPU環境下,矩陣相乘的執行速度明顯提高,但在維度較大的情況下,對程式碼進行優化會有更好的效果。
程式碼地址
個人GitHub:Icarusintheworld