在下面的代码中,我使用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)但是我注意到仍有一个区域确实落后 - 我在上面标注的最里面的循环。
我确定上面的数组导致错误共享,因为如果我在下面进行更改,我会看到性能上的另一个巨大飞跃(~40s到~13s)。
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 for循环,因为我依赖于为每次迭代计算的d_equ。
答案 0 :(得分:1)
在回答您的问题之前,我必须问一下,当您使用整个cells
作为函数some_calcutation()
的输入时,它是否真的是一种错误的共享情况?您似乎正在共享整个阵列。您可能想要提供有关此功能的更多信息。
如果是,请继续以下操作。
您已经证明私有变量double somevalue
可以提高性能。为什么不使用这种方法?
您可以在double
循环之前定义私有数组private_speed[10]
,而不是使用单个for k
变量,在循环中计算它们,然后将其复制回{{1在循环之后使用类似
cells