the OpenMP “master” pragma must not be enclosed by

2019-06-19 23:47发布

问题:

Why won't the intel compiler let me specify that some actions in an openmp parallel for block should be executed by the master thread only?

And how can I do what I'm trying to achieve without this kind of functionality?

What I'm trying to do is update a progress bar through a callback in a parallel for:

long num_items_computed = 0;

#pragma omp parallel for schedule (guided)
for (...a range of items...)
{
    //update item count
    #pragma omp atomic
        num_items_computed++;

    //update progress bar with number of items computed
    //master thread only due to com marshalling
    #pragma omp master
        set_progressor_callback(num_items_computed);

    //actual computation goes here
    ...blah...
}

I want only the master thread to call the callback, because if I don't enforce that (say by using omp critical instead to ensure only one thread uses the callback at once) I get the following runtime exception:

The application called an interface that was marshalled for a different thread.

...hence the desire to keep all callbacks in the master thread.

Thanks in advance.

回答1:

#include <omp.h>
void f(){}
int main()
{
#pragma omp parallel for schedule (guided)
    for (int i = 0; i < 100; ++i)
    {
        #pragma omp master
        f();
    }
    return 0;
}

Compiler Error C3034 OpenMP 'master' directive cannot be directly nested within 'parallel for' directive Visual Studio 2010 OpenMP 2.0

May be so:

long num_items_computed = 0;

#pragma omp parallel for schedule (guided)
for (...a range of items...)
{
    //update item count
    #pragma omp atomic
        num_items_computed++;

    //update progress bar with number of items computed
    //master thread only due to com marshalling
    //#pragma omp master it is error
    //#pragma omp critical it is right
    if (omp_get_thread_num() == 0) // may be good
        set_progressor_callback(num_items_computed);

    //actual computation goes here
    ...blah...
}


回答2:

The reason why you get the error is because the master thread isn't there most of the times when the code reaches the #pragma omp master line. For example, let's take the code from Artyom:

#include <omp.h>
void f(){}
int main()
{
#pragma omp parallel for schedule (guided)
    for (int i = 0; i < 100; ++i)
    { 
        #pragma omp master
            f();
    }
    return 0;
}

If the code would compile, the following could happen:

Let's say thread 0 starts (the master thread). It reaches the pragma that practically says "Master, do the following piece of code". It being the master can run the function. However, what happens when thread 1 or 2 or 3, etc, reaches that piece of code?

The master directive is telling the present/listening team that the master thread has to execute f(). But the team is a single thread and there is no master present. The program wouldn't know what to do past that point.

And that's why, I think, the master isn't allowed to be inside the for-loop.

Substituting the master directive with if (omp_get_thread_num() == 0) works because now the program says, "If you are master, do this. Otherwise ignore".