0
votes

I am trying to parallelize a for-loop with OpenMP. Usually this should be fairly straightforward. However I need to perform thread specific initializations prior to executing the for-loop.

Specifically I have the following problem: I have a random number generator which is not thread-safe so I need create an instance of the RNG for every thread. But I want to make sure that not every thread will produce the same random numbers.

So I tried the following:

    #pragma omp parallel
    {
        int rndseed = 42;
        #ifdef _OPENMP
            rndseed += omp_get_thread_num();
        #endif

         // initialize randon number generator

         #pragma omp for
         for (int sampleid = 0; sampleid < numsamples; ++sampleid)
         {
             // do stuff
         }
    }

If I use this construct I get the following error message at runtime:

Fatal User Error 1002: '#pragma omp for' improperly nested in a work-sharing construct

So is there a way to do thread-specific initializations?

Thanks

2
Why not seed each RNG from /dev/urandom, which will give you good seeds and different values each thread?Lee Daniel Crocker
I don't know why that's failing for you but to use random numbers see this stackoverflow.com/questions/10624755/…user2088790
The code that you are showing is not the cause of the problem. (You are not showing a work-sharing construct nested in a work-sharing construct). I expect that you actually have another #pragma omp for somewhere down inside "do stuff".Jim Cownie

2 Answers

0
votes

I think there's a design error.

A parallel for loop is not just N threads with N the number of cores for example, but potentially N*X threads, with 1 <= N*X < numsamples.

If you want an "iteration private" variable, then declare it just inside the loop-body (but you know that already); but declaring a thread-private variable for use inside a parallel for loop is probably not justified enough.

0
votes

The error you have:

Fatal User Error 1002: '#pragma omp for' improperly nested in a work-sharing construct

refers to an illegal nesting of worksharing constructs. In fact, the OpenMP 3.1 standard gives the following restrictions in section 2.5:

  • Each worksharing region must be encountered by all threads in a team or by none at all.
  • The sequence of worksharing regions and barrier regions encountered must be the same for every thread in a team.

From the lines quoted above it follows that nesting different worksharing constructs inside the same parallel region is not conforming.

Even though the illegal nesting is not visible in your snippet, I assume it was hidden by an oversimplification of the post with respect to the actual code. Just to give you an hint the most common cases are:

  • loop worksharing constructs nested inside a single construct (similar the example here)
  • loop worksharing constructs nested inside another loop construct

In case you are interested, in this answer the latter case is discussed more in details.