Search code examples
c++multithreadingopenmpdynamic-library

Destroying threads in Openmp (C++)


Is it possible to destroy the threads created by OpenMP? When the program starts, there is only the one thread. After the parallelized section multiple threads remain since there is a thread pool. Is there any way to destroy this pool after the parallel section is run?

I ask because I'm using OpenMP in a dynamic library, and the library handle cannot be closed while the threads are running (the program will segfault).

Thanks

More explanation: I'm putting all parallelization code into modules (shared libraries). I then load the module and pass it a class derived from an abstract base class. The module then 'runs' that class in parallel. This way, I can use no parallelization, OpenMP, MPI, or anything else and can change the parallel scheme at run time or even on the fly. But OpenMP doesn't destroy the threads, and when it comes time to manually dlclose the library, it will segfault since the resources are destroyed from underneath the thread (I believe). Letting the program finish without closing the library is probably ok for now, but wanting to manually close the library may still come up in the future (think changing scheme on the fly). Hope this makes sense :) Thanks


Solution

  • At this point in time, the OpenMP specification doesn't give the user any ability to control when threads are destroyed. What you are saying is very interesting and hasn't been brought up during any of the OpenMP language committee meetings to discuss the specification. Can you give more information about what you are doing and what the problem is? It would be helpful in bringing this discussion to the committee.

    Edit added 3/7 -

    Okay - here is a simple example that seems to work and it might get around your problem:

    $> cat prog.c  
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    
    int main(void)
    {
      void (*f)(void);
      void *handle;
    
      handle = dlopen("./shared.so", RTLD_NOW);
      if (!handle) {
        printf("*** dlopen error - %s\n", dlerror());
        abort();
      }
    
      f = dlsym(handle, "foo");
      if (!f) {
        printf("*** dlsym error - %s\n", dlerror());
        abort();
      }
      f();
    
      if(dlclose(handle)) {
        printf("*** dlclose error - %s\n", dlerror());
        abort();
      }
      return 0;
    }
    
    $> cat shared.c 
    #include <omp.h> 
    #include <stdio.h>
    
    void foo(void)
    {
      int i;
    
      puts("... in foo\n");
    
      #pragma omp parallel for
      for (i=0; i<10; i++) 
        printf("t#: %i  i: %i\n", omp_get_thread_num(), i);
    
      puts("... exiting foo");
    }
    
    $> gcc -rdynamic -fopenmp prog.c -ldl -o prog                                                                   
    $> gcc -c -fopenmp -fPIC -o shared.o shared.c                                                                 
    $> ld -shared -o shared.so shared.o                                                                           
    $> ./prog
    ... in foo
    
    t#: 2  i: 4
    t#: 2  i: 5
    t#: 3  i: 6
    t#: 3  i: 7
    t#: 0  i: 0
    t#: 0  i: 1
    t#: 4  i: 8
    t#: 4  i: 9
    t#: 1  i: 2
    t#: 1  i: 3
    ... exiting foo
    

    While there is no OpenMP code in the main program (prog.c), I compiled it using the -fopenmp flag. This means that the OpenMP environment will be set up before the call to the shared library that is actually using OpenMP. This seems to get around the problem with doing a dlclose, since the environment is still there. It also allows the threads gotten by the first use of OpenMP to stay around for subsequent use. Does this work for getting around your problem (or does this only work for this simple example)?