在openmp中进行for循环,与矩阵/向量操作并行

时间:2016-07-14 19:03:06

标签: c++ openmp

我有这段代码:

scalar State::add(const int N, const int M,                                                                                                                                                                                                                                               
                        vector<scalar>& flmn,                                                                                                                                                                                                                                             
                        vector<scalar>& BSum,                                                                                                                                                                                                                                             
                        const vector<scalar>& prev_flm,                                                                                                                                                                                                                                   
                        const vector<scalar>& prev_bigsum,                                                                                                                                                                                                                                
                        const vector<scalar>& Qratio,                                                                                                                                                                                                                                     
                        const int test)                                                                                                                                                                                                                                                   
{                                                                                                                                                                                                                                                                                         
  scalar c=1;                                                                                                                                                                                                                                                                          
  #pragma omp parallel for                                                                                                                                                                                                                                                                
  for(int i=1;i<=M;i++)                                                                                                                                                                                                                                                                   
   {                                                                                                                                                                                                                                                                                      
     flmn.at(i-1) = Qratio.at(i-1)*k1+k2;                                                                                                                                                                                                                                                 
     BSum.at(i-1) = someconstant + somepublicvector.at(1)*flmn.at(i-1);                                                                                                                                                                                                                   
     c *= BSum.at(i-1);                                                                                                                                                                                                                                                                   
   }                                                                                                                                                                                                                                                                                      
   return c;                                                                                                                                                                                                                                                                              
}                                                                                                                                                                                                                                                                                         

最后我返回变量c。使用时:&#34; #pragma omp parallel for&#34;它肯定不会给我一致的答案,因为迭代之间总是有重叠。我想知道矩阵或矢量操作的这种组合应该如何在openmp中并行化,而且我会得到一致的结果,因为这里显然存在竞争条件问题?

1 个答案:

答案 0 :(得分:1)

for (int i = 1; i <= M; i++) {
    flmn.at(i - 1) = Qratio.at(i - 1) * k1 + k2;
    BSum.at(i - 1) = someconstant + somepublicvector.at(1) * flmn.at(i - 1);
    c *= BSum.at(i - 1);
}

一些注意事项:

  1. 除非您确实需要异常安全索引,否则不要使用std::vector::at

  2. 您对每个向量使用相同的索引,因此从i=0而不是Fortran风格的i=1开始。

  3. M是否与正在使用的向量的大小不同(即,它是一个子集)?如果没有,则不需要指定。

  4. 然后可能是

    的可能的OpenMP实现
    scalar c{1.0};
    
    #pragma omp parallel
    {
        const std::size_t nthreads = omp_get_num_threads();
        const std::size_t chunk_size = M / nthreads;    // WARNING: non-even division case left to user
        const std::size_t tid = omp_get_thread_num();
    
        #pragma omp for reduction(*:c)
        for (std::size_t j = 0; j < chunk_size; j++) {
            const std::size_t i = j + tid * chunk_size;
            flmn[i] = Qratio[i] * k1 + k2;
            BSum[i] = someconstant + somepublicvector[1] * flmn[i];
            c *= BSum[i];
        }
    }
    

    请注意,我假设nthreads平均分为M。如果没有,则需要单独处理此案例。如果您使用的是OpenMP 4.0,那么我建议使用simd指令,因为前两行都是saxpy操作,可以从矢量化中受益。为获得最佳性能,请确保chunk_size是CPU的缓存行大小的倍数。