cov*_*tat 5 c++ random boost openmp
我从OpenMP并行代码段中得到"总线错误".我在下面重新创建了一个简单版本的问题.代码实际上对函数进行了很多调用,uniform_distribution
使用Boost的uniform_int_distribution绘制一个0到20000之间的整数.
这篇文章警告两个线程访问同一个对象.我猜这是eng
我的情况.(不幸的是,我不知道如何编写"合适的互斥包装器",正如该帖子所暗示的那样).
我想到的一个可能的脏解决方案是eng
在#pragma for
循环中创建一个局部并将其作为参数传递给uniform_distribution
.我不喜欢这个想法,因为在我的真实代码中,我正在调用许多函数,并且传递一个本地eng
会很麻烦.另外,我担心的是,如果我在内部声明,不同的线程将生成相同的随机数序列.所以我有两个要求:如何以某种方式并行化eng
uniform_distribution
谢谢; 任何帮助都热烈赞赏.
#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)
当您并行化某些代码时,您必须考虑共享资源,这可能会导致数据竞争,进而最终可能会破坏您的程序。(注意:并非所有数据竞争都会破坏您的程序。)
在您的情况下,正如您所预期的那样,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 中。struct
eng