Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

openmp : check if nested parallesim

Tags:

c++

openmp

Assume I have a method that multiplies two std::vector :

double multiply(std::vector<double> const& a, std::vector<double> const& b){
    double tmp(0);
    /*here I could easily do a parallelization with*/
    /*#pragma omp parallel loop for*/
    for(unsigned int i=0;i<a.size();i++){
        tmp += a[i]*b[i];
    }
    return tmp;
}

If I set in this function the pragma macro, a call to multiply(...) will run on all threads.

Now assume that somewehere else I want to do many vector multiplication :

void many_multiplication(std::vector<double>* a, std::vector<double>* b, unsigned int N){
    /*here I could easily do a parallelization with*/
    /*#pragma omp parallel loop for*/
    for(unsigned int i=0;i<N;i++){
        for(unsigned int j=0;j<N;j++){
            multiply(a[i],b[j]);
        }
    }
}

I could also do the parallelization the same way. But this will lead to unwanted nested parallelism.

How can I check that if multiply(..) is called within a parallel region, then the pragma macro of multiply(...) is "turn off". And if it's called from a non-parallel region, then it's "turn on".

like image 765
PinkFloyd Avatar asked Jul 20 '15 15:07

PinkFloyd


People also ask

Is nested parallelism possible in OpenMP?

OpenMP parallel regions can be nested inside each other. If nested parallelism is disabled, then the new team created by a thread encountering a parallel construct inside a parallel region consists only of the encountering thread. If nested parallelism is enabled, then the new team may consist of more than one thread.

What is #pragma OMP parallel sections?

Purpose. The omp parallel sections directive effectively combines the omp parallel and omp sections directives. This directive lets you define a parallel region containing a single sections directive in one step.

What is Omp_num_threads?

OMP_NUM_THREADS. Sets the maximum number of threads in the parallel region, unless overridden by omp_set_num_threads or num_threads. OMP_DYNAMIC. Specifies whether the OpenMP run time can adjust the number of threads in a parallel region.

What is Omp_set_dynamic?

SummaryThe omp_set_dynamic routine enables or disables dynamic adjustment of the number of threads available for the execution of subsequent parallel regions by setting the value of the dyn-var ICV.


2 Answers

Nested parallelism is disabled by default, unless enabled specificially by setting OMP_NESTED to true or by calling omp_set_nested(1); (§2.3.2 of the OpenMP specification) Explicitly modifying the settings for nesting as suggested by Avi Ginsburg is a bad idea. Instead, you should use conditional parallel execution based on the level of nesting:

double multiply(std::vector<double> const& a, std::vector<double> const& b){
    double tmp(0);
    int active_levels = omp_get_active_level();
    #pragma omp parallel for reduction(+:tmp) if(active_level < 1)
    for(unsigned int i=0;i<a.size();i++){
        tmp += a[i]+b[i];
    }
    return tmp;
}

omp_get_active_level() returns the number of active parallel regions that enclose the thread at the moment the call is made. It returns 0 if called from outside a parallel region or with inactive outer region(s). Thanks to the if(active_level < 1) clause, the parallel region will only be activated, i.e. run in parallel, if it is not enclosed in an active region, regardless of the setting for nesting.

If your compiler does not support OpenMP 3.0 or higher (e.g. with any version of MS Visual C/C++ Compiler), then omp_in_parallel() call can be used instead:

double multiply(std::vector<double> const& a, std::vector<double> const& b){
    double tmp(0);
    int in_parallel = omp_in_parallel();
    #pragma omp parallel for reduction(+:tmp) if(in_parallel == 0)
    for(unsigned int i=0;i<a.size();i++){
        tmp += a[i]+b[i];
    }
    return tmp;
}

omp_in_parallel() returns non-zero if at least one enclosing parallel region is active, but does not provide information about the depth of nesting, i.e. is a bit less flexible.

In any case, writing such code is a bad practice. You should simply leave the parallel regions as they are and allow the end user choose whether nested parallelism should be enabled or not.

like image 156
Hristo Iliev Avatar answered Sep 25 '22 14:09

Hristo Iliev


Add the pragma to both functions. You can turn the nested parallelism on and off with omp_set_nested(int val) (zero for off, non-zero for on).

So, if you wanted nested parallelism on in your program in general, but off for the many_multiplication function, you would implement many_multiplication as follows:

void many_multiplication(std::vector<double>* a, std::vector<double>* b, unsigned int N){
    omp_set_nested(0);
    #pragma omp parallel loop for
    for(unsigned int i=0;i<N;i++){
        for(unsigned int j=0;j<N;j++){
            multiply(a[i],b[j]);
        }
    }
    omp_set_nested(1);
}
like image 43
Avi Ginsburg Avatar answered Sep 25 '22 14:09

Avi Ginsburg