Мой вопрос касается использования OpenMP в функциях C++, хранящихся в динамических библиотеках. Рассмотрим следующий код (в shared.cpp):
#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;
}
};
Я компилирую этот код с помощью g++: g++ -fopenmp -shared -fPIC -o shared.so shared.cpp. Затем, чтобы использовать функцию test, у меня есть следующая программа (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;
}
компилируется с помощью команды: g++ -o main main.cpp -ldl Проблема в том, что ошибка сегментации возникает в самом конце выполнения программы. По словам valgrind, на данный момент некоторые потоки все еще активны, что, похоже, согласуется с поведением OpenMP.
Одно решение (для кода C) из this post состоит в том, чтобы скомпилируйте программу, используя флаг gcc -fopenmp, но g++ кажется достаточно умным, чтобы обнаружить, что OpenMP никогда не используется в этой программе, и среда OpenMP никогда не загружается (код сборки обеих версий одинаков) . Единственный обходной путь, который я нашел, - это сделать бесполезный вызов OpenMP в программе, что заставляет g++ загрузить среду OpenMP, и тогда выполнение будет правильным. Но для меня этот обходной путь довольно уродлив. Я пробовал g++-4.8.2, g++-4.8.1, g++-4.7.3 и g++-4.6.4. (В icc-14 использование опции -openmp в программе действительно решает проблему).
Кто-нибудь когда-нибудь сталкивался с этой проблемой? Есть ли более чистое обходное решение? Спасибо, Томас
Изменить Пробовал с G++-4.9.2: по-прежнему не получается