Выпуск GIL в PyBind11 для многопоточности в Python с OpenMP - PullRequest
1 голос
/ 14 января 2020

Я использую Pybind11 и пытаюсь использовать в нем OpenMP. Я вызываю функцию c ++ из Python, используя интерпретатор PyBind и GIL, затем вычисляю многопоточность для l oop с OpenMP в c ++, в котором в каждом потоке я вызываю python функцию. Для этого я сначала ограничиваю область действия GIL py::gil_scoped_release release; до параллельной области, а затем восстанавливаю ее вне параллельной области с помощью `py :: gil_scoped_acquire acqu;

Проблема заключается в многопоточности для л oop. Мне нужно создать интерпретатор для каждого потока. У меня вопрос: как это сделать?

Сначала я подумал об использовании py::scoped_interpreter guard{}, но в документации сказано, что:

Создание двух одновременных охранников scoped_interpreter является фатальной ошибкой. Так что> вызывается initialize_interpreter () во второй раз после того, как интерпретатор уже был инициализирован.

Не используйте сырые CPython API-функции Py_Initialize и Py_Finalize, поскольку они неправильно обрабатывают время жизни Внутренние данные pybind11.

Второй момент довольно проблематичен, так как имеется больше документации, но только с использованием Python C -API, не имеющим дело с объектами Pybind 1 2 3

Я посмотрел документацию , но она не решает точно мою проблему, потому что она не вызывает Python в многопоточности. Я также посмотрел на это 4 , но интерпретатор вызывается из c ++, а не 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
...