在下面的代码中,我使用 OpenMP 的标准parallel for
子句进行了并行化。
#pragma omp parallel for private(i, j, k, d_equ) shared(cells, tmp_cells, params)
for(i=0; i<some_large_value; i++)
{
for(j=0; j<some_large_value; j++)
{
....
// Some operations performed over here which are using private variables
....
// Accessing a shared array is causing False Sharing
for(k=0; k<10; k++)
{
cells[i * width + j].speeds[k] = some_calculation(i, j, k, cells);
}
}
}
这让我的运行时间有了显着改善(~140s 到 ~40s),但我注意到仍然有一个领域确实落后了——我在上面标记的最里面的循环。
我肯定知道上面的数组会导致错误共享,因为如果我在下面进行更改,我会看到性能的另一个巨大飞跃(约 40 秒到约 13 秒)。
for(k=0; k<10; k++)
{
double somevalue = some_calculation(i, j);
}
换句话说,只要我将内存位置更改为写入私有变量,就会有巨大的加速提升。
在我刚刚解释的场景中,有什么方法可以通过避免错误共享来改善我的运行时间?即使问题本身被提及很多,我似乎也无法在网上找到许多似乎有助于解决此问题的资源。
我有一个想法来创建一个过大的数组(需要的 10 倍),以便在每个元素之间保持足够的边距空间,以确保当它进入缓存行时,没有其他线程会拾取它。然而,这未能产生预期的效果。
是否有任何简单的(或者如果需要的话甚至很难)方法来减少或删除该循环中发现的错误共享?
任何形式的见解或帮助将不胜感激!
编辑:假设 some_calculation() 执行以下操作:
(tmp_cells[ii*params.nx + jj].speeds[kk] + params.omega * (d_equ[kk] - tmp_cells[ii*params.nx + jj].speeds[kk]));
我无法将此计算移出我的 for 循环,因为我依赖于为每次迭代计算的 d_equ。