给定n部分和,可以将log2并行步骤中的所有部分和相加.例如,假设有八个线程与八个部分和:s0, s1, s2, s3, s4, s5, s6, s7.这可以在这样的log2(8) = 3连续步骤中减少;
thread0     thread1    thread2    thread4
s0 += s1    s2 += s3   s4 += s5   s6 +=s7
s0 += s2    s4 += s6
s0 += s4
我想用OpenMP做这个,但我不想使用OpenMP的reduction子句.我想出了一个解决方案,但我认为可以使用OpenMP的task子句找到更好的解决方案.
这比标量加法更通用.让我选择一个更有用的情况:一个数组减少(见这里,这里,并在这里为更多关于阵列减少).
假设我想在阵列上进行数组缩减a.下面是一些代码,它们为每个线程并行填充私有数组.
int bins = 20;
int a[bins];
int **at;  // array of pointers to arrays
for(int i = 0; i<bins; i++) a[i] = 0;
#pragma omp …我想使用OpenMP并行填充直方图.我在C/C++中使用OpenMP提出了两种不同的方法.
第一种方法为每个线程proccess_data_v1创建一个私有直方图变量hist_private,并行填充它们,然后将私有直方图加到hist一个critical部分中的共享直方图中.
第二种方法生成proccess_data_v2一个直方图的共享数组,其数组大小等于线程数,并行填充此数组,然后并行地对共享直方图求和hist.  
第二种方法似乎优于我,因为它避免了临界区并且并行地对直方图求和.但是,它需要知道线程数和调用omp_get_thread_num().我一般都试图避免这种情况.有没有更好的方法来执行第二种方法而不引用线程数并使用大小等于线程数的共享数组?
void proccess_data_v1(float *data, int *hist, const int n, const int nbins, float max) {
    #pragma omp parallel 
    {
        int *hist_private = new int[nbins];
        for(int i=0; i<nbins; i++) hist_private[i] = 0;
        #pragma omp for nowait
        for(int i=0; i<n; i++) {
            float x = reconstruct_data(data[i]);
            fill_hist(hist_private, nbins, max, x);
        }
        #pragma omp critical 
        {
            for(int i=0; i<nbins; i++) {
                hist[i] += hist_private[i];
            }
        } …我正在尝试为复杂<float>的向量定义自己的减少,在对OpenMP中的数组减少问题的答案之后.
但是我的向量的大小在编译时并不固定,所以我不确定如何在declare reductionpragma中为向量定义初始化器.也就是说,我不能拥有
initializer( omp_priv=TComplexVector(10,0) )
但是矢量需要初始化器.
如何在运行时传递我需要的向量大小的初始化子句?我到目前为止的内容如下:
typedef std::vector<complex<float>> TCmplxVec;
void ComplexAdd(TCmplxVec & x,TCmplxVec & y){
  for (int i=0;i<x.size();i++) 
  {
      x.real()+= y.real();
      //... same for imaginary part and other operations
  }
}
#pragma omp declare reduction(AddCmplx: TCmplxVec: \
ComplexAdd(&omp_out, &omp_in)) initializer( \
omp_priv={TCmplxVec(**here I want a variable length**,0} )
void DoSomeOperation ()
{
    //TCmplxVec vec is empty and anotherVec not
    //so each thread runs the inner loop serially
  #pragma omp parallel for reduction(AddCmplx: …我刚刚开始使用 openmp 进行编程,我正在尝试使用for循环外需要的变量来并行化循环。像这样的东西:
float a = 0;
for (int i = 0; i < x; i++)
{
    int x = algorithm();
    /* Each loop, x have a different value*/
    a = a + x;
}
cout << a;
我认为该变量a必须是每个线程的局部变量。这些线程结束其工作后,所有局部变量a都应添加到一个最终结果中。
我怎样才能做到这一点?
我想让这段代码并行:
std::vector<float> res(n,0);
std::vector<float> vals(m);
std::vector<float> indexes(m);
// fill indexes with values in range [0,n)
// fill vals and indexes
for(size_t i=0; i<m; i++){
  res[indexes[i]] += //something using vas[i];
}
在这个文章它的建议使用:
#pragma omp parallel for reduction(+:myArray[:6])
在这个问题中,评论部分提出了相同的方法.
我有两个问题:
m在编译时,从这两个例子看来,它似乎是必需的.是这样吗?或者,如果我可以在这种情况下使用它,我需要?在以下命令中替换#pragma omp parallel for reduction(+:res[:?])什么?m还是n?for是相对于indexes和vals,而不是res,尤其是考虑到reduction是在后者做了什么?但是,如果是这样,我该如何解决这个问题呢?
假设我有一个f(i)依赖于索引的函数i(以及无法预先计算的其他值)。我想填充一个数组,a以便a[n] = sum(f(i)) from i=0 to n-1.
编辑:在 Hristo Iliev 发表评论后,我意识到我在做什么是一个累积/前缀总和。
这可以用代码编写为
float sum = 0;
for(int i=0; i<N; i++) {
    sum += f(i);
    a[i] = sum;
}
现在我想使用 OpenMP 并行执行此操作。我可以用 OpenMP 做到这一点的一种方法是f(i)并行写出 的值,然后串行处理依赖关系。如果f(i)是一个慢函数,那么这可以很好地工作,因为非并行循环很简单。
#pragma omp parallel for
for(int i=0; i<N; i++) {
    a[i] = f(i);
}
for(int i=1; i<N; i++) {
    a[i] += a[i-1];
}
但是可以在没有 OpenMP 的非并行循环的情况下做到这一点。然而,我想出的解决方案很复杂,而且可能是骇人听闻的。所以我的问题是,是否有一种更简单、更简单的方法来使用 OpenMP 做到这一点?
下面的代码基本上运行我为每个线程列出的第一个代码。结果是a给定线程中的值在一个常量内是正确的。我将每个线程的总和保存到一个suma …
我有以下一段代码。
for (i = 0; i < n; ++i) {
  ++cnt[offset[i]];
}
其中offset是大小的阵列n包含值的范围[0, m)和cnt是大小的数组m初始化为0。我使用的OpenMP并行它如下。
#pragma omp parallel for shared(cnt, offset) private(i)
for (i = 0; i < n; ++i) {
  ++cnt[offset[i]];
}
根据这篇文章的讨论,如果offset[i1] == offset[i2]为i1 != i2,上面的代码可能会导致错误cnt。我该怎么做才能避免这种情况?