假设我有以下C代码,并且想使用OpenMP对其进行并行化。
for (int i = 0; i < n; ++i)
{
int key = get_key(i);
toArray[count[key]++] = fromArray[i];
}
我知道如果我直接使用并行语法,这可能会导致数据争用并得到错误的答案,但是如果我使用“严重”,则性能将非常差。
#pragma omp parallel for schedule(static)
for (int i = 0; i < n; ++i)
{
int key = get_key(i);
#pragma omp criical
toArray[count[key]++] = fromArray[i];
}
我想知道是否有一种方法可以使其具有良好的性能并行化?
答案 0 :(得分:1)
恐怕您的假设是错误的。带有关键部分的版本确实会给出正确的答案-至少不是确定性的答案。
为简单起见,以get_key
总是返回0
的情况为例。串行版本将复制该阵列,而并行版本将执行任意重组。 get_key
返回相同值的所有迭代之间都存在顺序依赖性。
一般来说。简单的关键部分通常可以用简化来代替,该简化允许独立执行,同时在并行部分之后产生一些合并开销。原子操作也可以作为简单操作的一种选择,但是它们也会遭受一般性能下降和通常还会带来负面缓存问题的困扰。从技术上讲,您不正确的关键部分代码将等效于以下更有效的原子代码:
int index;
#pragma omp atomic capture
index = count[key]++;
#pragma omp atomic write
toArray[index] = fromArray[i];
我想知道是否有一种方法可以使其具有良好的性能并行化?
关于性能的任何问题都需要更具体的信息。涉及的类型,数据大小,并行度……是什么?对于“这是提高性能的最佳方式” ,没有普遍的答案。