如何使用OpenMP并行化数组移位?

时间:2011-05-17 12:18:42

标签: openmp permutation parallel-processing

如何使用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;
}

非常感谢!

2 个答案:

答案 0 :(得分:4)

虽然你的样本没有显示任何明确的openmp pragma,但我认为它不会轻易起作用:

您正在进行重叠区域的就地操作。 如果你将循环分成块,你将在边界处有竞争条件(因为el [n]从el [n + 1]复制,可能已经在另一个线程中更新过了。)

我建议你做手动分块(可以这样做),但我怀疑openmp parallel for不够灵活(没试过),所以你可以只有一个并行区域来完成块的工作,并在线程障碍/并行块结束后修复边界元素


其他想法:

  1. 如果您的值是POD,则可以使用memmove
  2. 如果可以,只需切换到列表
  3. 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;
}