Я использую Pybind11 и пытаюсь использовать в нем OpenMP. Я вызываю функцию C++ из Python, используя интерпретатор PyBind и GIL, затем я вычисляю многопоточный цикл for с OpenMP в C++, в котором я вызываю в каждом потоке функцию Python. Для этого я сначала ограничиваю область GIL с помощью py::gil_scoped_release release;
до параллельной области, а затем восстанавливаю ее за пределами параллельной области с помощью `py::gil_scoped_acquire Acquire;
Проблема внутри многопоточного цикла for. Мне нужно создать интерпретатор для каждого потока. Мой вопрос: как это сделать?
Сначала я подумал об использовании py::scoped_interpreter guard{}
, но в документации сказано, что:
Создание двух параллельных охранников scoped_interpreter является фатальной ошибкой. То же самое происходит с >вызовом initialize_interpreter() во второй раз после того, как интерпретатор уже был инициализирован.
Не используйте необработанные функции API CPython Py_Initialize и Py_Finalize, так как они неправильно обрабатывают время жизни внутренних данных pybind11.
Второй момент представляет собой настоящую проблему, так как документации больше, но только с использованием Python C-API, а не с объектами Pybind 1 2 3а>
Я просмотрел документацию, но она не решает именно мою проблему, потому что не не вызывать Python в многопоточности. Я также просмотрел этот 4, но интерпретатор вызывается из С++, а не из Python
Любая подсказка будет высоко оценена, так как я довольно долго был заблокирован по этой проблеме. Вот пример кода для иллюстрации проблемы.
py::object create_seq(
py::object self
){
std::vector<py::object> dict = self.cast<std::vector<py::object>>();
py::gil_scoped_release release;
#pragma omp parallel for ordered schedule(dynamic)
for(unsigned int i=0; i<dict.size(); i++) {
?? WHAT HAPPENS HERE ??
std::cout << i << std::endl;
#pragma omp ordered
dict[i].attr("attribute") = open.attr("parallel")().cast<int>();
}
py::gil_scoped_acquire acquire;
return self;
}
PYBIND11_MODULE(error, m){
m.doc() = "pybind11 module for iterating over generations";
m.def("create_seq", &create_seq,
"the function which creates a sequence");
}
Код Python
import error
class test():
def __init__(self):
self.attribute = None
def func():
return 2
if __name__ == '__main__':
dict = {}
for i in range(50):
dict[i] = test()
pop = error.create_seq(list(dict.values()))
Составлено
g++ -O3 -Wall -shared -std=c++14 -fopenmp -fPIC `python3 -m pybind11 --includes` openmp.cpp -o error.so
gstate
со всеми потоками, записывающими в него. ЕслиPyGILState_Ensure
правильно блокирует, это может сработать, но я бы не стал на это полагаться. - person Wim Lavrijsen   schedule 15.01.2020PyGILState_Ensure
получает блокировку - person Sergei   schedule 16.01.2020