gpt4 book ai didi

c - OpenMP 错误共享和缓存命中利用

转载 作者:行者123 更新时间:2023-11-30 17:46:03 25 4
gpt4 key购买 nike

在我的代码中,有几种方法包含用于在 ny*nx 矩阵中移动的嵌套循环。我想并行化这个过程,所以我在每个方法上都使用了这样的东西:

#pragma omp parallel for private(jj,x_e,x_w,y_n,y_s)
for(ii=0;ii<ny;ii++) {
for(jj=0;jj<nx;jj++) {
/* determine indices of axis-direction neighbours
** respecting periodic boundary conditions (wrap around) */
y_n = (ii + 1) % ny;
x_e = (jj + 1) % nx;
y_s = (ii == 0) ? (ii + ny - 1) : (ii - 1);
x_w = (jj == 0) ? (jj + nx - 1) : (jj - 1);
//propagate densities to neighbouring cells, following
tmp[ii *nx + jj].speeds[0] = cells[ii*nx + jj].speeds[0]; /* central cell, */
/* no movement */
tmp[ii *nx + x_e].s[1] = cells[ii*nx + jj].s[1]; /* east */
tmp[y_n*nx + jj].s[2] = cells[ii*nx + jj].s[2]; /* north */
tmp[ii *nx + x_w].s[3] = cells[ii*nx + jj].s[3]; /* west */
tmp[y_s*nx + jj].s[4] = cells[ii*nx + jj].s[4]; /* south */
tmp[y_n*nx + x_e].s[5] = cells[ii*nx + jj].s[5]; /* north-east */
tmp[y_n*nx + x_w].s[6] = cells[ii*nx + jj].s[6]; /* north-west */
tmp[y_s*nx + x_w].s[7] = cells[ii*nx + jj].s[7]; /* south-west */
tmp[y_s*nx + x_e].s[8] = cells[ii*nx + jj].s[8]; /* south-east */
}
}

但是,这段代码(以及其他代码)非常慢。有什么方法可以纠正我的#pragma 语句并重写数据结构或循环以使其缓存友好并避免错误共享?

PS:代码是使用 -O3 编译的,因此每次微小优化的尝试都没有实现任何加速。

最佳答案

设置线程并向它们分配工作会带来一些开销。由于您的工作尺寸较小(200x300),并且工作很简单(只有一些数据副本),因此线程开销甚至可能比您的实际工作更大,这就是您没有获得性能改进的原因之一。

另一个原因是,由于使用了结构数组 (AoS),您的代码的缓存本地化效果很差。特别是当您写入 tmp 时。为了获得更好的缓存命中性能,您可以考虑使用数组结构(SoA)。事实上你只需要交换尺寸

cells[nx*ny][9]

cells[9][nx*ny]

然后你会发现部分复制可以直接用memcpy()完成。

另一方面,我不认为您的代码存在严重的错误共享问题。

关于c - OpenMP 错误共享和缓存命中利用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19466989/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com