首页 > 解决方案 > Pybind11:使用 for 循环使用 OpenMP 访问 python 对象

问题描述

我正在尝试对 python 字典的所有元素操作 c++ 函数。为此,我在字典的所有元素上使用 c++ 中的 for 循环。#pragma omp parallel for simd在这种情况下,据我所知,可以使用该子句加快速度。但是,当我运行它时,我得到了错误:

GC 对象已跟踪
进程以退出代码 139 完成(被信号 11:SIGSEGV 中断)

编辑

我在这篇文章中读到,问题来自在 c++ 中访问 Python 对象的方式,但是它没有进一步讨论。我猜这个问题来自于访问具有多个线程的 python 对象。我目前仍在寻找。

任何提示将不胜感激。

提前非常感谢。

C++ 代码

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/stl.h>
#include <omp.h>
#include <chrono>
#include <thread>

namespace py = pybind11;
py::module nn = py::module::import("neat.nn");

py::object create_seq(
  py::object self
  ){

  unsigned int z;
  #pragma omp parallel for simd
  for(z = 0; z < 50000; z++){
      double value = self.attr("dict").attr("__getitem__")(z).cast<double>();
      value *=2;
      self.attr("dict").attr("__setitem__")(z, value);
  }
  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 os
import error

class func():
    def __init__(self):

        dictionary = {}
        for i in range(50000):
            dictionary[i] = i

        self.dict = dictionary
        self.array = None

    def modify_dict(self):
        return error.create_seq(self)

if __name__ == '__main__':
    # Determine path to configuration file. This path manipulation is
    # here so that the script will run successfully regardless of the
    # current working directory.
    local_dir = os.path.dirname(__file__)
    a = func()
    a.modify_dict()
    print(a.dict)

编译:

g++ -O3 -Wall -shared -std=c++14 -fopenmp -fPIC `python3 -m pybind11 --includes` openmp.cpp -o error.so

标签: pythonc++openmppybind11

解决方案


问题确实是使用多个线程访问 python 对象。我不知道确切的原因,但这根本不可能。诀窍是将您的 python 对象转换为 python 对象列表,必须将其转换为向量。只有这样,多个线程才能访问向量的各种 python 对象。

就我而言,我传递的不是整个字典,而是列表中字典的值,然后将此列表转换为 python 对象的向量。

在简历中,它类似于:

error.create_seq(list(dict.values()))

在 C++ 中:

std::vector<py::object> = dict.cast<std::vector<py::object>>();

然后#pragma omp parallel可以应用该子句


推荐阅读