我正在研究C++中的多重網格解算器,現在我正在嘗試改進串行性能。這裏最耗時的部分是平滑的,在我的情況下是連續的過度鬆弛求解器。這看起來如下(我希望這是相當自我解釋):優化3D循環(C++)
int idx;
int strideY = stride_[level][0];
int strideZ = stride_[level][1];
for(int i = 0; i < steps; ++i) {
for(int z = 1; z <= innerGridpoints_[level][2]; ++z) {
for(int y = 1; y <= innerGridpoints_[level][1]; ++y) {
idx = getIndexInner(level, 1,y,z);
for(int x = 1; x <= innerGridpoints_[level][0]; ++x, ++idx) {
grid[idx] = (1. - omega) * grid[idx] + omega * 1./6. * (grid[idx+1] + grid[idx-1] +
grid[idx + strideY] + grid[idx - strideY] +
grid[idx + strideZ] + grid[idx - strideZ] -
spacing_[level] * spacing_[level] * rhs[idx]);
}
}
}
}
我已經做了一些優化:這些環定位使得內環給出了最本地條目(即相鄰元素是沿x維度)和預先計算idx(即使這是一個內聯函數,它可以節省相當一段時間)。 我也嘗試過阻塞,即不是遍歷整個網格,而只是在小塊上增加局部性,但這沒有任何影響。 我最後的想法是嘗試一些循環展開,但我實際上並不期望從中得到很大的改進。我在想,也許在內存訪問方面有一些可能的改進。任何tipps歡迎:)
只是供參考:網格大小會從非常小到255x255x255不等。此外,網格在每個維度都有一些邊界,由少量的行組成,即迭代不在整個網格上。
您是否打算在(10,10,10)處進行平滑以在同一平滑過程中更改(10,10,11)處的結果? – Yakk 2013-03-20 22:17:54
@Yakk:對不起,我不太明白你的意思? (10,10,10)處的平滑僅改變此值。你的意思是像紅黑一樣嗎?這是通常用於並行化,但我保持純串行 – Chris 2013-03-20 22:35:51
不,我的意思是你修改'grid [10,10,10]',然後在設置'grid [10,10,11]'(I' m使用'[a,b,c]'來表示「做所有的索引計算以找出a,b,c處的項目是''grid [getIndexInner(level,10,10,10)]'而不是'格[10,10,10]'是剛剛被詳細說明) – Yakk 2013-03-20 23:38:17