有一段代码
<AndroidDexTool>d8</AndroidDexTool>
似乎可以与 #pragma omp parallel for
一起正常使用或不带
(已检查输出)。但是我不明白以下几点:
1)不同的并行线程访问类Dbase的对象dbase的相同数组x和y(我知道OpenMP隐式地使dbase对象共享,即 #pragma omp共享(dbase) ) 。不同的线程不会在这些数组中写入,而只会读取。但是,当他们阅读时,是否存在从x和y读取的竞争条件?如果不是,那么如何组织每时每刻从interpolate()中的x和y读取1个线程,并且不同的线程不会互相打扰?也许在每个OpenMP线程中都有dbase对象及其x和y数组的本地副本(但它等效于 #pragma omp与private(dbase)并行)?
2)我是否可以用这样的代码编写 #pragma omp parallel for shared(dbase)或 #pragma omp parallel for 是否足够?
3)我认为,如果我在for循环中放置1个随机数生成器,以使其正常工作(而不是使其内部状态处于竞争状态),我应该写
#include <iostream>
#include <array>
#include <random>
#include <omp.h>
class DBase
{
public:
DBase()
{
delta=(xmax-xmin)/n;
for(int i=0; i<n+1; ++i) x.at(i)=xmin+i*delta;
y={1.0, 3.0, 9.0, 15.0, 20.0, 17.0, 13.0, 9.0, 5.0, 4.0, 1.0};
}
double GetXmax(){return xmax;}
double interpolate(double xx)
{
int bin=xx/delta;
if(bin<0 || bin>n-1) return 0.0;
double res=y.at(bin)+(y.at(bin+1)-y.at(bin)) * (xx-x.at(bin))
/ (x.at(bin+1) - x.at(bin));
return res;
}
private:
static constexpr int n=10;
double xmin=0.0;
double xmax=10.0;
double delta;
std::array<double, n+1> x;
std::array<double, n+1> y;
};
int main(int argc, char *argv[])
{
DBase dbase;
const int N=10000;
std::array<double, N> rnd{0.0};
std::array<double, N> src{0.0};
std::array<double, N> res{0.0};
unsigned seed = 1;
std::default_random_engine generator (seed);
for(int i=0; i<N; ++i) rnd.at(i)=
std::generate_canonical<double,std::numeric_limits<double>::digits>(generator);
#pragma omp parallel for
for(int i=0; i<N; ++i)
{
src.at(i)=rnd.at(i) * dbase.GetXmax();
res.at(i)=dbase.interpolate(rnd.at(i) * dbase.GetXmax());
}
for(int i=0; i<N; ++i) std::cout<<"("<<src.at(i)<<" , "<<res.at(i)
<<") "<<std::endl;
return 0;
}
#pragma omp原子将破坏 #pragma omp parallel 的性能提升(会使线程等待)。因此,如何在并行区域内使用随机数的唯一正确方法是为每个线程拥有自己的生成器(或种子)或在for循环之前准备所有需要的随机数。正确吗?