使用一致的RNG与OpenMP

  • 本文关键字:RNG OpenMP c++ openmp
  • 更新时间 :
  • 英文 :


我有一个函数,我们叫它dostuff(),它有时对我的应用程序并行化是有益的,或者多次并行化整个东西。该函数在两个用例之间不会改变。

注意:object足够大,不能存储在列表中,因此每次迭代都必须丢弃它。

我们的代码是这样的:

bool parallelize_within = argv[1];
if (parallelize_within) {
// here we assume parallelization is handled within the function dostuff()
for (int i = 0; i < 100; ++i) {
object randomized = function_that_accesses_rand();
dostuff(i, randomized, parallelize_within);
}
} else {
#pragma omp parallel for
for (int i = 0; i < 100; ++i) {
object randomized = function_that_accesses_rand();
dostuff(i, randomized, parallelize_within);
}
}

显然,我们遇到了dostuff()会让线程在同一程序的不同迭代中在不同时间访问随机对象的问题。这不是parallelize_within == true时的情况,但是当我们并行运行dostuff()时,每个线程单独运行,是否有一种方法可以保证随机对象是根据迭代顺序访问的?我知道我能做到:

#pragma omp parallel for schedule(dynamic)

将保证最终,当迭代在运行时动态地分配给线程时,对象将按照迭代号的顺序访问rand,但对于第一组迭代,它将完全随机。对于如何避免这种情况有什么建议吗?

  1. 首先你必须确保function_that_accesses_randdo_stuff都是线程安全的。

  2. 如果你使用if子句,你不必复制你的代码:#pragma omp parallel for if(!parallelize_within)

  3. 要确保在dostuff(i, randomized,...);i函数中反映randomized对象的创建顺序,您必须这样做:

int j = 0;
#pragma omp parallel for if(!parallelize_within)
for (int i = 0; i < 100; ++i) {
int k;
object randomized;
#pragma omp critical
{
k = j++;
randomized = function_that_accesses_rand();        
}
dostuff(k, randomized, parallelize_within);
}
  1. 如果您的function_that_accesses_rand使其成为可能,您可以消除critical部分的使用,但在不了解您的功能的情况下,我无法更具体。一种解决方案是,该函数返回表示订单的值。不要忘记这个函数必须是线程安全的!
#pragma omp parallel for if(!parallelize_within)
for (int i = 0; i < 100; ++i) {
int k;
object randomized = function_that_accesses_rand(k);        
dostuff(k, randomized, parallelize_within);
}
... function_that_accesses_rand(int& k){
...  
#pragma omp atomic capture
k = some_internal_counter++;
...
} 

您可以预先生成随机对象并将其存储在列表中。然后在omp循环中添加一个变量,每个线程增加一个。

// generate random objects
i=0
#pragma omp parallel for
for( ... ){
do_stuff(...,rand_obj[i],...)

最新更新