提振.Python不支持并行
boost.python not supporting parallelism?
我正在尝试使用boost将一段c++代码包装成python库。但是,我发现多个实例不能同时运行:
代码(c++):class Foo{
public:
Foo(){}
void run(){
int seconds = 2;
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
};
BOOST_PYTHON_MODULE(run_test)
{
using namespace boost::python;
class_<Foo>("test", init<>())
.def("run", &Foo::run)
;
}
使用CMake (CMake)编译:
add_library(run_test SHARED run_test.cpp)
target_link_libraries(run_test boost_python python2.7)
并使用以下代码(Python)进行测试:
class Dos(threading.Thread):
def run(self):
printl('performing DoS attack')
proc = test()
proc.run()
for i in range(5):
t = Dos()
t.start()
输出表明代码以一种非常奇怪的方式并行化。在我的四核机器上,每个线程应该只需要2秒,并且4个线程应该同时运行:
[2011-11-04 13:57:01] performing DoS attack
[2011-11-04 13:57:01] performing DoS attack
[2011-11-04 13:57:05] performing DoS attack
[2011-11-04 13:57:05] performing DoS attack
[2011-11-04 13:57:09] performing DoS attack
谢谢你的帮助!
您正在运行的是python全局解释器锁。GIL只允许在python解释器中一次运行一个线程。
Boost的优点之一。Python的优点是,你可以释放GIL,做c++的事情,然后在完成后收回它。然而,这也是一种责任。Python通常会定期释放GIL,以便给其他线程一个运行的机会。如果你使用c++,这就是你的工作。如果你拿着GIL花2个小时处理数字,你会冻结整个解释器。
这可以很容易地修复,用一点反向RAII:
class releaseGIL{
public:
inline releaseGIL(){
save_state = PyEval_SaveThread();
}
inline ~releaseGIL(){
PyEval_RestoreThread(save_state);
}
private:
PyThreadState *save_state;
};
现在你可以这样修改你的代码:
class Foo{
public:
Foo(){}
void run(){
{
releaseGIL unlock = releaseGIL();
int seconds = 2;
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
}
};
非常重要的是要注意,在不持有GIL的情况下,绝对不能触摸任何python代码或python数据或调用解释器。这将导致解释器崩溃。
反过来也有可能。当前不持有GIL的线程可以获取它,并对python进行调用。这可以是一个较早释放GIL的线程,也可以是一个在c++中启动并且从未有过GIL的线程。下面是RAII类:
class AcquireGIL
{
public:
inline AcquireGIL(){
state = PyGILState_Ensure();
}
inline ~AcquireGIL(){
PyGILState_Release(state);
}
private:
PyGILState_STATE state;
};
用法留给学生练习。
附加说明(我总是忘记提到这一点):
如果你要在c++中搞乱GIL,你的模块定义需要从这段代码开始:
BOOST_PYTHON_MODULE(ModuleName)
{
PyEval_InitThreads();
...
}
相关文章:
- 为什么istream不支持右值提取
- 错误:(-210:不支持的格式或格式组合)功能'create'中的硬件视频解码器不支持视频源
- Casablanca/cpprestsdk listener.support接受函数,但不支持方法
- 为什么C++不支持对未初始化变量进行智能分析?
- 在 c++ 中连接字符串和整数,以便在 C++ 11 不支持计算机的情况下读取多个文件
- 在 Ubuntu 18.04 上编译 GLSL 着色器时"不支持 GLSL 3.30"?
- 为什么联机C++ IDE 不支持"graphics.h"头文件?
- Clang编译器不支持aarch64-apple-darwin上的-fxray-instrument
- 为什么我的 clang 格式不支持 PPDirectiveIndentStyle 选项?
- 为什么某些 STL 容器(堆栈、队列、优先级队列)不支持迭代器?
- 为什么不支持 Xcode 1.5?
- C++20 从括号中的值列表初始化聚合,不支持内部数组
- 为什么结构化绑定不支持可变数组?
- 您选择的 CPU 不支持 x86-64 指令集
- 将数据发送到多个客户端 UDP 时不支持地址族
- 缺少类型说明符 - 假定为 int.注意 c++ 不支持 default-int
- 瓦尔格林德"不支持arch_prctl选项"
- 错误:C4430:缺少类型说明符-假定为int.注意:C++不支持default-int
- 抢占模式下不支持 CUDA 动态并行调试.断点将被禁用
- 提振.Python不支持并行