Boost Random and OpenMP

I get a "bus error" from a parallel section of OpenMP code. I recreated a simple version of my problem below. The code essentially makes many calls to a function uniform_distributionthat draws an integer from 0 to 20,000 using Boost uniform_int_distribution.

This post warns of two threads accessing the same object. I guess engin my case. (Unfortunately, I don't know how to write a “suitable mutex wrapper,” as this post suggests).

A possible dirty solution that I was thinking about is to create a local one enginside the loop #pragma forand pass it as an argument uniform_distribution. I do not like this idea, because in my real code I call many functions, and going through the local one engwill be cumbersome. Also, I am worried that different threads will generate a sequence of the same random numbers if I declare enginside uniform_distribution. Therefore, I have two requirements: how do I parallelize so that

  • Does each thread generate probabilistically independent draws from other threads?
  • RNG missing race conditions

Thank; any help is appreciated.

#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;
}
+5
source share
3 answers

, , , , . (: .)

, , eng , .

- : . eng.

eng:

(1) threadprivate (): , #pragma omp threadprivate(eng). , POD .

(2) threadprivate , eng : declare, eng[MAX_THREAD]. : eng[omp_get_thread()].

, . , eng[MAX_THREAD] , 64 . . : , char padding[x] struct, eng.

+3

, thread_local RNG , , , XOR . - ( ++ 11):

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

#include <thread>
#include <ctime>

boost::random::mt19937& get_rng_engine() {
  thread_local boost::random::mt19937 eng(
    reinterpret_cast<unsigned int>(std::time(NULL)) ^ std::this_thread::get_id());
  return eng;
};

(: <random>, ++ 11)

++ 11, boost::thread , , . Boost thread-local .

+3

:

  • -.

-, :

# pragma omp parallel for
for (int bb=0; bb<10000; bb++)
{
    for (int i=0; i<20000; i++)
    {
        // enter critical region, disallowing simulatneous access to eng
        #pragma omp critical
        {
            int a = uniform_distribution(0,20000);
        }
        // presumably some more code...
    }
    // presumably some more code...
}

, :

# pragma omp parallel
{
    // declare and seed thread-specific generator
    boost::random::mt19937 eng(omp_get_thread_num());
    #pragma omp for
    for (int bb=0; bb<10000; bb++)
    {
        for (int i=0; i<20000; i++)
        {
            int a = uniform_distribution(0,20000, eng);
            // presumably some more code...
        }
        // presumably some more code...
    }
}

, (, , ), . , . , , , , , ( , ). ( ).

- , .

EDIT. To be clear, mutual exclusion solutions make sense if random number generation is not a major part of the work of threads (that is // presumably some more code..., the example exists and doesn't take a trivial amount of time to complete). The critical section should cover only access to the shared variable, but changing your architecture a bit will allow you to more precisely control this (and in the case of local thread storage, it can also allow you to bypass the link eng))

0
source

All Articles