如何使用OpenMP并行化数组移位?
我尝试了一些方法,但没有得到以下示例的任何准确结果(旋转Carteira对象数组的元素,用于置换算法):
void rotaciona(int i)
{
Carteira aux = this->carteira[i];
for(int c = i; c < this->size - 1; c++)
{
this->carteira[c] = this->carteira[c+1];
}
this->carteira[this->size-1] = aux;
}
非常感谢!
答案 0 :(得分:4)
虽然你的样本没有显示任何明确的openmp pragma,但我认为它不会轻易起作用:
您正在进行重叠区域的就地操作。 如果你将循环分成块,你将在边界处有竞争条件(因为el [n]从el [n + 1]复制,可能已经在另一个线程中更新过了。)
我建议你做手动分块(可以这样做),但我怀疑openmp parallel for不够灵活(没试过),所以你可以只有一个并行区域来完成块的工作,并在线程障碍/并行块结束后修复边界元素
其他想法:
std::list<Carteira> items(3000);
// rotation is now simply:
items.push_back(items.front());
items.erase(items.begin());
答案 1 :(得分:4)
这是一个带loop-carried dependencies的循环的示例,因此无法轻松并行化,因为任务(循环的每次迭代)都不是独立的。打破依赖可以从简单的修改到完全不可能的改变 (例如,迭代循环)。
这里,情况介于两者之间。并行执行此操作的问题是,您需要在邻居更改值之前找出最右边的值。构造的OMP不向您揭示哪些循环迭代值将是“您的”,因此我认为您不能使用OpenMP for worksharing构造来分解循环。但是,你可以自己做;但它需要更多的代码,并且它不会很好地减少到串行的情况。
但是,如何执行此操作的示例如下所示。你必须自己打破循环,然后获得最正确的价值。 OpenMP屏障确保在所有线程都缓存了新的最右边的值之前,没有人开始修改值。
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char **argv) {
int i;
char *array;
const int n=27;
array = malloc(n * sizeof(char) );
for (i=0; i<n-1; i++)
array[i] = 'A'+i;
array[n-1] = '\0';
printf("Array pre-shift = <%s>\n",array);
#pragma omp parallel default(none) shared(array) private(i)
{
int nthreads = omp_get_num_threads();
int tid = omp_get_thread_num();
int blocksize = (n-2)/nthreads;
int start = tid*blocksize;
int end = start + blocksize - 1;
if (tid == nthreads-1) end = n-2;
/* we are responsible for values start...end */
char rightval = array[end+1];
#pragma omp barrier
for (i=start; i<end; i++)
array[i] = array[i+1];
array[end] = rightval;
}
printf("Array post-shift = <%s>\n",array);
return 0;
}