Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do c++11 threads become unjoinable when using nested OpenMP pragmas?

The following code should be pretty straightforward but seems to end up in a hanging situation when trying to do a .join() on the threads with nested OpenMP code. Using GCC compiler 4.7.2 x64 with pthreads from http://sourceforge.net/projects/mingwbuilds with g++ threadexample.cpp -Wall -std=c++11 -fopenmp -o threads

// threadexample.cpp
#include <iostream>
#include <thread>
#include <omp.h>

using namespace std;

void hello(int a) {

    #pragma omp parallel for
        for (int i=0;i<5;++i) {
            #pragma omp critical
            cout << "Hello from " << a << "! " << "OMP thread iter " << i << endl;
        }

    cout << "About to return from hello function" << endl;
}

int main (int argc, char ** argv) {

    thread t1(hello, 1); //fork
    cout << "t1 away!" << endl;
    thread t2(hello, 2);
    cout << "t2 away!" << endl;

    t1.join(); //join
    cout << "thread 1 joined" << endl;
    t2.join();
    cout << "thread 2 joined" << endl;

    return 0;
}
like image 823
illumi Avatar asked Nov 02 '12 14:11

illumi


1 Answers

Mixing OpenMP and any other threading library (pthreads, Win32 threading, etc.) might not be a good idea. The OpenMP run-time might be written with the presumption that it is fully in control of threading and might not support parallel regions being run concurrently (e.g. it might use global variables like semaphores to control the thread pools).

A better pure OpenMP way to implement this would be:

#include <iostream>
#include <omp.h>

using namespace std;

void hello(int a) {

    #pragma omp parallel for
    for (int i=0;i<5;++i) {
        #pragma omp critical
        cout << "Hello from " << a << "! " << "OMP thread iter " << i << endl;
    }

    cout << "About to return from hello function" << endl;
}

int main (int argc, char ** argv) {

    omp_set_nested(1);

    #pragma omp parallel sections num_threads(2)
    {
       #pragma omp section
       {
           hello(1);
       }
       #pragma omp section
       {
           hello(2);
       }
    }

    return 0;
}

The call to omp_set_nested() is needed in order to enable nested parallelism which is disabled by default.

like image 190
Hristo Iliev Avatar answered Oct 30 '22 13:10

Hristo Iliev