我正在研究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