我有这段代码:
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中并行化,而且我会得到一致的结果,因为这里显然存在竞争条件问题?
答案 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);
}
一些注意事项:
除非您确实需要异常安全索引,否则不要使用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的缓存行大小的倍数。