[問題] 如何讓計算速度發揮到極限

看板C_and_CPP作者 (輕子)時間12年前 (2013/08/14 23:05), 編輯推噓8(8045)
留言53則, 7人參與, 最新討論串1/5 (看更多)
hi,hi 感謝各位之前熱情的回覆讓我學到用binary方式寫檔案 我才發現原來binary的方式這麼好用 小的我有另外的問題想請教大家 在做流體計算時繁複的計算我都是丟到GPU上計算 計算的效率幾乎都是2TLOPs以上,可以發揮到顯示卡計算能力極限的70%左右 (以GTX680為例2 FLOPS/Clock × 1006 MHz × 1536 = 3.090 TFLOPS) 但是同樣的計算放到CPU上都<10GFLOPs,幾乎不到CPU計算能力極限的10% (以Ivy Bridge為例 8 FLOPS/Clock × 3.5GHz ×4 = 102.4 GFLOPS ) 乍看之下GPU好像加速幾乎上百上千倍的計算速度但其實CPU根本沒發揮真本事 在GPU的情況編譯器會把乘加合併成一條指令去做才能做到2 FLOPS/Clock 那在CPU的部分要啟用SSE指令集或AVX指令集的話是要自己去編寫嗎?還是編譯器會做? 因為我在VC2010 中加入/arch:AVX之類的指令但速度並沒有增加 我這邊做的事情基本上就是迭代計算 vector<vector<double> > V, VNew ,rho; void Jacobi() { #pragma omp parallel for for (int i = 1; i <= L; i++) #pragma omp parallel for for (int j = 1; j <= L; j++) VNew[i][j] = 0.25 * (V[i - 1][j] + V[i + 1][j] + V[i][j - 1] + V[i][j + 1] + h * h * rho[i][j]); } -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 1.170.79.135

08/14 23:27, , 1F
如果可以的話,以 Debug 啟動反組譯並且修改相對的組合語言
08/14 23:27, 1F

08/14 23:29, , 2F
碼,必竟編譯器產生的組合語言碼有部份是可以做最佳化使效率
08/14 23:29, 2F

08/14 23:29, , 3F
提升.
08/14 23:29, 3F

08/14 23:30, , 4F
這code看起來關鍵反而是cache
08/14 23:30, 4F

08/14 23:31, , 5F
像 V[i-1][j] 與 V[i+1][j] 這種很傷 CPU cache 的效能
08/14 23:31, 5F

08/14 23:34, , 6F
因為換算成一維的位址會差很遠,一般情況容易miss
08/14 23:34, 6F

08/14 23:34, , 7F
但GPU的cache會考慮二維甚至三維的情況
08/14 23:34, 7F

08/14 23:35, , 8F
在這方面的效能會比CPU快很多
08/14 23:35, 8F

08/14 23:39, , 9F
如果只處理小型資料的話可以儘量不用 vector<> 而改以內建
08/14 23:39, 9F

08/14 23:39, , 10F
vector根本沒差好嗎
08/14 23:39, 10F

08/14 23:40, , 11F
若在 CPU 上要加速,首先不要用一列一列的方式處理
08/14 23:40, 11F

08/14 23:40, , 12F
陣列方式,因為每呼叫一次 operator[] 與 operator +() CPU
08/14 23:40, 12F

08/14 23:41, , 13F
改用以 block 為單位 (比如 8x8) 加強 cache coherence
08/14 23:41, 13F

08/14 23:43, , 14F
就必需花時間計算使用與返回的堆疊空間,可以從組合語言程式
08/14 23:43, 14F

08/14 23:44, , 15F
看出.
08/14 23:44, 15F

08/14 23:52, , 16F
然後若要利用到SSE,在這例子中要把內層迴圈拆開
08/14 23:52, 16F
可以給點示範嗎?拆掉內層迴圈無所謂 ※ 編輯: Lepton 來自: 1.170.79.135 (08/14 23:56)

08/14 23:57, , 17F
cache miss panelty比改動esp/ebp及branch miss所要花的
08/14 23:57, 17F

08/14 23:57, , 18F
cycle大太多了 先如l大考慮cache會比較好
08/14 23:57, 18F

08/15 00:00, , 19F
branch prediction miss^
08/15 00:00, 19F
hi,我知道在GPU也有cache的問題但在CPU上要怎樣處理這個問題我不熟悉 請問可以給點參考資料嗎?我先google研究看看不懂再來提問好了 ※ 編輯: Lepton 來自: 1.170.79.135 (08/15 00:02)

08/15 00:05, , 20F
你先參考 matrix multiplication 對 cache locality
08/15 00:05, 20F

08/15 00:05, , 21F
的最佳化的一些作法和原因 可以得到一些靈感~
08/15 00:05, 21F

08/15 00:32, , 22F
operator[]都inline掉了沒人在返回堆疊的啦
08/15 00:32, 22F

08/15 00:33, , 23F
最佳化開下去vector存取跟陣列一模一樣
08/15 00:33, 23F

08/15 00:42, , 24F
這裡的例子使用 vector<> 但沒使用到如 insert() 或是
08/15 00:42, 24F

08/15 00:43, , 25F
push_back() 類似的演算法函式,只單純做四則運算,這裡看到
08/15 00:43, 25F

08/15 00:46, , 26F
用了 operator+(), operator[](), operator*(),那為什麼不
08/15 00:46, 26F

08/15 00:47, , 27F
用內建的四則運算功能呢?CPU 在呼叫這些函式都需要成本考量
08/15 00:47, 27F

08/15 00:50, , 28F
它只會呼叫operator[]() 我想你是看錯了某些地方
08/15 00:50, 28F

08/15 00:54, , 29F
http://ideone.com/r5BfvV operator[]也沒有真的叫下去
08/15 00:54, 29F

08/15 00:55, , 30F
真的要說就是ctor效率差和unroll等最佳化做的比較不好
08/15 00:55, 30F
QQ這邊大家討論的東西好深奧我都不懂!看來我C/C++沒學好 ※ 編輯: Lepton 來自: 111.252.0.105 (08/15 01:00)

08/15 01:13, , 31F
哈~對不起這裡只會呼叫 operator[]()
08/15 01:13, 31F

08/15 01:14, , 32F
以 azureblaze 提供的組合語言碼,可以看到呼叫建構子時 CPU
08/15 01:14, 32F

08/15 01:17, , 33F
初使化的暫存器,然後又呼叫建構物件的函式,又是一個負擔,
08/15 01:17, 33F

08/15 01:20, , 34F
這些都是 CPU 在呼叫這些函式所花費的成本,如果這裡用了內
08/15 01:20, 34F

08/15 01:21, , 35F
建陣列的話完全不需要這些動作,而且執行檔會相對的較小.
08/15 01:21, 35F

08/15 01:47, , 36F
azureblaze你沒開最佳化對不對XD 我的連ctor都inline了
08/15 01:47, 36F

08/15 01:53, , 37F
不過也對啦 內建陣列有時候可以幫你省下delete的時間
08/15 01:53, 37F

08/15 01:53, , 38F
因為忘了呼叫嘛 XDDDDDDDDDDD
08/15 01:53, 38F

08/15 02:08, , 39F
MSVC12好像沒最佳化那邊
08/15 02:08, 39F

08/15 06:08, , 40F
何必算上下左右座標,直接平移好位置,四片直接加,
08/15 06:08, 40F

08/15 06:09, , 41F
根本不需要計算下標及浪費時間存取,也不需要cache
08/15 06:09, 41F

08/15 08:43, , 42F
我覺得如果真的要最佳化,為什麼不自已來做呢?
08/15 08:43, 42F

08/15 08:46, , 43F
用了內建陣列就是最佳化的方法,而且也省下了配置記憶體花費
08/15 08:46, 43F

08/15 08:46, , 44F
的時間.
08/15 08:46, 44F

08/15 10:45, , 45F
以這例子來說轉置90度也算是個好方法了
08/15 10:45, 45F

08/15 10:46, , 46F
至於平移....我想不出有什麼不用計算下標的平移方式耶
08/15 10:46, 46F

08/15 11:06, , 47F
如果真的要用 vector<>, 或許 vector<int> 的 operator[]()
08/15 11:06, 47F

08/15 11:07, , 48F
比 vector<vector<int>> 的還要有效率,必竟 inline 只是請
08/15 11:07, 48F

08/15 11:09, , 49F
求,編譯器會視情況使用.
08/15 11:09, 49F

08/15 13:09, , 50F
這麼簡單的運算,容易卡在memory bandwidth
08/15 13:09, 50F

08/15 16:42, , 51F
所以要盡量降低cache miss
08/15 16:42, 51F

08/15 23:07, , 52F
這邊已經是計算機組織的問題了 和語言其實關係比較小
08/15 23:07, 52F

08/15 23:07, , 53F
簡單的說就是如何最高效率的應用硬體減少多餘步驟
08/15 23:07, 53F
文章代碼(AID): #1I2vp5YO (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1I2vp5YO (C_and_CPP)