我试图将一段C ++代码与OpenMp并行化,但我遇到了一些问题。 实际上,我的并行化代码并不比串行代码快。 我想我已经理解了这个原因,但是我无法解决它。
我的代码结构如下:
int vec1 [M];
int vec2 [N];
...initialization of vec1 and vec2...
for (int it=0; it < tot_iterations; it++) {
if ( (it+1)%2 != 0 ) {
#pragma omp parallel for
for (int j=0 ; j < N ; j++) {
....code involving a call to a function to which I'm passing as a parameter vec1.....
if (something) { vec2[j]=vec2[j]-1;}
}
}
else {
# pragma omp parallel for
for (int i=0 ; i < M ; i++) {
....code involving a call to a function to which I'm passing as a parameter vec2.....
if (something) { vec1[i]=vec1[i]-1;}
}
}
}
我认为可能我的并行化代码速度较慢,因为多个线程想要访问同一个共享阵列,而且必须等到另一个完成,但我不确定事情是怎么回事。但我无法将vec1和vec2设为私有,因为在其他迭代中无法看到更新... 我怎样才能改进它?
答案 0 :(得分:0)
当您在使用多个线程访问同一阵列时谈到问题时,这称为“假共享”。除非您的数组很小,否则它不应该是瓶颈,因为pragma omp parallel for
在默认实现中使用静态调度(至少使用gcc)所以每个线程应该访问大部分数组而不是可靠性,除非你的“..涉及调用函数的代码,我将其作为参数传递给vec2 ......“真的可以访问数组中的很多元素。
案例1:您不会在代码的这一部分访问数组中的大多数元素
尝试移动并行区域代码:
int vec1 [M];
int vec2 [N];
...initialization of vec1 and vec2...
#pragma omp parallel
for (int it=0; it < tot_iterations; it++) {
if ( (it+1)%2 != 0 ) {
#pragma omp for
for (int j=0 ; j < N ; j++) {
....code involving a call to a function to which I'm passing as a parameter vec1.....
if (something) { vec2[j]=vec2[j]-1;}
}
}
else {
# pragma omp for
for (int i=0 ; i < M ; i++) {
....code involving a call to a function to which I'm passing as a parameter vec2.....
if (something) { vec1[i]=vec1[i]-1;}
}
}
这不应该有太大变化,但某些实现会产生代价高昂的并行区域。
案例2:您可以使用每个线程访问每个元素
我会说如果你执行更新就不能这样做,否则,你可能会遇到一致性问题,因为你在循环中有顺序依赖。