提升随机和OpenMP

cov*_*tat 5 c++ random boost openmp

我从OpenMP并行代码段中得到"总线错误".我在下面重新创建了一个简单版本的问题.代码实际上对函数进行了很多调用,uniform_distribution使用Boost的uniform_int_distribution绘制一个0到20000之间的整数.

这篇文章警告两个线程访问同一个对象.我猜这是eng我的情况.(不幸的是,我不知道如何编写"合适的互斥包装器",正如该帖子所暗示的那样).

我想到的一个可能的脏解决方案是eng#pragma for循环中创建一个局部并将其作为参数传递给uniform_distribution.我不喜欢这个想法,因为在我的真实代码中,我正在调用许多函数,并且传递一个本地eng会很麻烦.另外,我担心的是,如果我在内部声明,不同的线程将生成相同的随机数序列.所以我有两个要求:如何以某种方式并行化enguniform_distribution

  1. 每个线程都从其他线程生成概率独立的绘制?
  2. RNG没有竞争条件?

谢谢; 任何帮助都热烈赞赏.

#include <omp.h>
#include <boost/random/uniform_int_distribution.hpp>

boost::random::mt19937  eng;

int uniform_distribution(int rangeLow, int rangeHigh) {
    boost::random::uniform_int_distribution<int> unirv(rangeLow, rangeHigh);
    return unirv(eng);
}
int main()
{  
    # pragma omp parallel for private(eng)
    for (int bb=0; bb<10000; bb++)
        for (int i=0; i<20000; i++)
             int a = uniform_distribution(0,20000);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

min*_*ang 3

当您并行化某些代码时,您必须考虑共享资源,这可能会导致数据竞争,进而最终可能会破坏您的程序。(注意:并非所有数据竞争都会破坏您的程序。)

在您的情况下,正如您所预期的那样,eng是由两个或多个线程共享的,为了正确执行必须避免这种情况。

针对您的情况的解决方案是私有化:为共享资源制作每个线程的副本。您需要创建一个单独的副本eng

有多种方法可以进行私有化eng

(1) 尝试使用threadprivate指令(link):例如,#pragma omp threadprivate(eng). 但是,某些编译器可能不支持该指令的非 POD 结构。

(2) 如果 wherethreadprivate不可用,请使用数组eng并通过线程 id 进行访问:声明如eng[MAX_THREAD]。然后,使用线程 id: 进行访问eng[omp_get_thread()]

然而,第二种解决方案需要考虑错误共享,这会严重损害性能。最好保证中的每个项目都eng[MAX_THREAD]分配在单独的缓存行边界上,在现代桌面 CPU 中,该边界通常为 64 字节。还有多种方法可以避免错误共享。最简单的解决方案是使用填充:例如,在包含 的char padding[x]a 中。structeng