La mia domanda riguarda l'uso di OpenMP in funzioni C++ memorizzate in librerie dinamiche. Consideriamo il seguente codice (in shared.cpp):Errore ingannevole con OpenMP in funzione caricato da librerie dinamiche
#include "omp.h"
#include <iostream>
extern "C" {
int test() {
int N = omp_get_max_threads();
#pragma omp parallel num_threads(N)
{
std::cout << omp_get_thread_num() << std::endl;
}
return 0;
}
};
ho compilare il codice utilizzando g ++: g ++ -fopenmp -shared -fPIC -o shared.so shared.cpp. Quindi, utilizzare la funzione prova, ho il seguente programma (main.cpp):
#include <iostream>
#include <dlfcn.h>
int main() {
void* handle = dlopen("./shared.so", RTLD_NOW);
if (!handle) {
std::cerr << "can not open shared.so" << std::endl;
return 1;
}
int(*f)() = (int(*)()) dlsym(handle,"test");
if (!f) {
std::cerr << "can not find 'test' symbol in shared.so" << std::endl;
return 1;
}
(*f)();
if (dlclose(handle)) {
std::cerr << "can not close shared.so" << std::endl;
return 1;
}
return 0;
}
compilato con il comando: g ++ -o main.cpp principale -ldl Il problema è che un l'errore di segmentazione si verifica alla fine dell'esecuzione del programma. Secondo valgrind, alcuni thread sono ancora attivi a questo punto, che sembra essere coerente con il comportamento di OpenMP.
Una soluzione (per il codice C) da this post è per compilare il programma utilizzando il gcc -fopenmp bandiera, ma g ++ sembra abbastanza intelligente per rilevare che OpenMP non viene mai usata in quel programma, e l'ambiente OpenMP è mai caricato (il codice assembly di entrambe le versioni è uguale). L'unica soluzione che ho trovato è quella di effettuare una chiamata inutile ad OpenMP nel programma, che forza g ++ a caricare l'ambiente OpenMP e l'esecuzione è corretta. Ma per me questa soluzione è abbastanza brutta. Ho provato g ++ - 4.8.2, g ++ - 4.8.1, g ++ - 4.7.3 e g ++ - 4.6.4. (con icc-14, l'utilizzo dell'opzione -openmp sul programma risolve effettivamente il problema).
Qualcuno ha mai affrontato questo problema? C'è un workaround più pulito? Grazie, Thomas
Modifica provato con G ++ - 4.9.2: non riesce ancora