Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用OpenMP分配阵列的特殊指令?_C++_Performance_Openmp - Fatal编程技术网

C++ 使用OpenMP分配阵列的特殊指令?

C++ 使用OpenMP分配阵列的特殊指令?,c++,performance,openmp,C++,Performance,Openmp,我在OpenMP中针对并行化的简单循环是 vector< double > xs; vector< double > ys; xs.resize(N); ys.resize(N); if(rank0) printf("Assigning points ...\n"); #pragma omp parallel for for(long i = 0; i < N; i++) { xs[i] = ((d

我在
OpenMP
中针对并行化的简单
循环是

    vector< double > xs; 
    vector< double > ys; 
    xs.resize(N);
    ys.resize(N);
    if(rank0) printf("Assigning points ...\n");
#pragma omp parallel for
    for(long i = 0; i < N; i++) {
        xs[i] = ((double)rand()/(double)RAND_MAX);
        ys[i] = ((double)rand()/(double)RAND_MAX);
    } 
vectorxs;
向量ys;
xs.resize(N);
ys.resize(N);
如果(rank0)printf(“分配点…\n”);
#pragma-omp并行
用于(长i=0;i
但是当我为
包含
#pragma omp parallel时,这要比不包含时花费更长的时间。当我没有使用正确的
减少值
或类似的东西时,经常会出现这种情况,因此我想知道我是否还需要为此
#pragma
做些什么

for
循环是否需要
#pragma
中的其他内容


请注意,这个问题与使用
rand()

直接相关。我的直接猜测是,问题源于
rand()
使用一个种子,该种子在每次调用
rand()
时都会更新。这意味着,即使正在写入的数组之间没有冲突,对
rand()
的每次调用都可能会强制线程之间进行同步

处理这个问题有多种方法。一个显而易见的方法是使用C++11中提供的新随机数生成类,每个线程都有一个单独的随机数生成器对象,如下所示:

    std::mt19937_64 a;
    std::mt19937_64 b;

    std::uniform_real_distribution<double> da;
    std::uniform_real_distribution<double> db;

#pragma omp parallel for private(a, b)
    for (long i = 0; i < N; i++) {
        xs[i] = da(a);
        ys[i] = db(b);
    }
std::mt19937_64 a;
标准:mt19937_64 b;
std::均匀实分布da;
标准:均匀实分布数据库;
#pragma omp并行专用(a、b)
用于(长i=0;i
至少在我的系统上的一个快速测试中,单线程运行大约4秒,启用OpenMP时运行大约1秒(这是在一个4核处理器上,因此接近完美的扩展)

请注意,如果您使用的是32位系统(或至少使用生成32位代码的编译器),那么如果您使用
mt19937
而不是
mt19937\u 64
,这可能会大大加快速度。对于每个生成的数字,这将只有32位随机性,但这可能与
rand()
产生的随机性一样多。在64位系统/编译器上,期望
mt19937\u 64
运行同样快,并产生更大的随机性


另一个小提示:这里我刚刚为每个生成器使用了默认种子(即
1
)。您可能希望随机生成种子,例如从
std::random_device
,并分别为每个线程的生成器种子,这样就不会在线程之间获得重复的数字。

事实证明,
rand
不是线程安全的。一个简单的选择是
drand48\u r
,这是我试图使用的。如下所示更改我的循环显示了我所期望的确切加速:

#pragma omp parallel for private(ii, rBuf, trand) shared(xs,ys)
    for(ii = 0; ii < N; ii++) {
        drand48_r(&rBuf, &trand);
        xs[ii] = trand;
        drand48_r(&rBuf, &trand);
        ys[ii] = trand;
    } 
#专用(ii、rBuf、trand)共享(xs、ys)的pragma omp并行
对于(ii=0;ii
你在哪个平台上,N的价值是什么?Linux(我认为这无关紧要)和
N
500050000
。可能是@OMGtechy的重复:它最初看起来可能是重复的,但我不认为是。使用
rand()
的具体细节(我相信)在这里非常相关(见我的答案)。