作为Python C API的学习过程,我试图在传递给tbb parallel_for的functor中调用Python函数。 调用该函数的操作崩溃了Python进程的实例。 我没有做任何不线程安全的事情。我从列表中获取项目然后我调用Python函数,并将项目作为参数传递给函数。最后,我将项目设置回列表。什么提示我做错了什么?
答案 0 :(得分:1)
当您从C ++调用Python函数时,很可能忘记抓取Global Interpreter Lock(GIL)。例如,使用implements this的Python swig的TBB模块:
class PyCaller : public swig::SwigPtr_PyObject {
public:
using swig::SwigPtr_PyObject::SwigPtr_PyObject; // gets constructors
void operator()() const {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
PyObject* r = PyObject_CallFunctionObjArgs((PyObject*)*this, NULL);
if(r) Py_DECREF(r);
SWIG_PYTHON_THREAD_END_BLOCK;
}
};
// Usage:
tbb::task_group tg;
void enqueue( PyObject *c ) {
tg.run( PyCaller(c) );
}
您可以看到SWIG如何实现它 - here。
要考虑的其他选项包括使用Numba的@cfunc(nopython=True)
装饰器和Cython的nogil
属性,这些属性可以使函数更快并使Python的函数能够并行运行他们从已编译的函数中删除GIL。