问题描述
我从一个OpenMP parallel代码段得到一个总线错误。我在下面重新创建了我的问题的简单版本。代码本质上对函数 uniform_distribution
进行许多调用,它使用Boost的uniform_int_distribution绘制一个介于0和20000之间的整数。
I'm getting a "bus error" from an OpenMP parallel section of code. I recreated a simple version of my problem below. The code essentially makes many calls to the function uniform_distribution
, which draws an integer between 0 and 20000 using Boost's uniform_int_distribution.
此警告两个线程访问同一对象。我想在我的情况下是 eng
。 (不幸的是我不知道如何写一个适当的互斥包装器,正如该帖所表明的)。
This post warns of two threads accessing the same object. I'm guessing that's eng
in my case. (Unfortunately I don't know how to write "an appropriate mutex wrapper", as that post suggests).
一个可能的肮脏的解决方案我想是创建一个本地在 #pragma for
循环中的 eng
,并将其作为参数传递给 uniform_distribution
。我不喜欢这个想法,因为在我的实际代码中,我调用许多函数,并传递一个本地
eng
将是麻烦。此外,我关心的是,如果我在 uniform_distribution $中声明
eng
,不同的线程将生成相同 c $ c>。所以我有两个要求:我如何以一种方式并行化
A possible dirty solution I thought of was to create a local eng
inside the #pragma for
loop and to pass that as an argument to uniform_distribution
. I don't like this idea because in my real code, I'm calling many functions, and passing a local eng
would be cumbersome. Also, my concern is that different threads will generate the same random number sequence if I declare eng
inside uniform_distribution
. So I have two requirements: How do I parallelize in a way that
- 每个线程生成概率独立从其他线程抽取?
- 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;
}
推荐答案
您必须考虑共享资源,这可能导致数据竞争,反过来,最终可能会打破您的程序。
When you parallelize some code, you must consider the shared resource, which can cause data races, in turn, eventually may break your program. (Note: not all data races will break your program.)
在您的情况下,正如您所期望的, eng
In your case, as you expected correctly, eng
is the shared by two or more threads, which must be avoided for the correct execution.
您的情况的解决方案是私有化:make共享资源的每线程副本。您需要创建 eng
的单独副本。
A solution for your case is privatization: making a per-thread copy for the shared resources. You need to create a separate copy of eng
.
有很多方法可以私有化 eng
:
There are a number of way to do privatization for eng
:
(1)尝试使用 threadprivate
指令):例如, #pragma omp threadprivate(eng )
。但是,一些编译器可能不支持此P伪指令的非POD结构。
(1) Try to use threadprivate
directive (link): For example, #pragma omp threadprivate(eng)
. However, some compilers may not support non-POD structures for this directive.
(2)如果 threadprivate
不可用,使用 eng
数组,并使用线程id:declare例如 eng [MAX_THREAD]
进行访问。然后,使用线程ID访问: eng [omp_get_thread()]
。
(2) In case where threadprivate
is not available, use an array of eng
and access with thread id: declare such as eng[MAX_THREAD]
. Then, access with thread id: eng[omp_get_thread()]
.
false共享,这可能严重损害性能。最好确保 eng [MAX_THREAD]
中的每个项目分配在单独的缓存行边界上,在现代桌面CPU中通常为64字节。还有几种方法可以避免假分享。最简单的解决方案是在 struct
中使用填充: char padding [x]
c> eng 。
However, the second solution needs to consider false sharing, which can severely hurt the performance. It's best to guarantee each item in eng[MAX_THREAD]
is allocated on separate cache line boundary, which is typically 64-byte in modern desktop CPUs. There are also several ways to avoid false sharing. The simplest solution would be using padding: e.g., char padding[x]
in a struct
that holds eng
.
这篇关于Boost随机和OpenMP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!