Python C,待定,从多个线程调用一个函数
Python C, tbb, calling a function from multiple threads
作为 Python C API 的学习过程,我正在尝试调用传递给 tbb parallel_for 的仿函数内部的 Python 函数。
调用函数的操作使 Python 进程的实例崩溃。
我没有做任何线程不安全的事情。我从列表中获取该项目,然后调用 Python 函数,并将该项目作为参数传递给该函数。最后,我将该项目设置回列表。任何提示我做错了什么?
很可能是您在从 C++ 调用 Python 函数时忘记获取全局解释器锁 (GIL)。例如,Python implements this using 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)
decorator and Cython's nogil
属性,这既可以使函数更快,又可以使 Python 的函数与 运行 并行,因为它们从编译函数中删除了 GIL。
作为 Python C API 的学习过程,我正在尝试调用传递给 tbb parallel_for 的仿函数内部的 Python 函数。 调用函数的操作使 Python 进程的实例崩溃。 我没有做任何线程不安全的事情。我从列表中获取该项目,然后调用 Python 函数,并将该项目作为参数传递给该函数。最后,我将该项目设置回列表。任何提示我做错了什么?
很可能是您在从 C++ 调用 Python 函数时忘记获取全局解释器锁 (GIL)。例如,Python implements this using 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)
decorator and Cython's nogil
属性,这既可以使函数更快,又可以使 Python 的函数与 运行 并行,因为它们从编译函数中删除了 GIL。