我有以下代码:

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。当使用这个:“ #pragma omp parallel for”时,肯定不会给我一致的答案,因为迭代之间总是存在重叠。我不知道如何在openmp中并行处理矩阵或矢量操作的这种组合,并且由于这里显然存在竞争条件问题,我是否还会得到一致的结果?

最佳答案

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);
}


一些注意事项:


除非确实需要异常安全索引,否则不要使用std::vector::at
每个向量使用相同的索引,因此从i=0开始,而不是从Fortran样式的i=1开始。
M是否与所使用向量的大小不同(即它是一个子集)?如果不是,则无需指定。




然后可能的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的缓存行大小的倍数。

关于c++ - 在openmp中进行for循环,与矩阵/vector 操作并行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38382272/

10-14 16:44