Python游戏server开发日记(二)绕过GIL启动多线程Python环境
2017-06-28 14:26
507 查看
说道Python和多线程,非常easy想到GIL,GIL意味着仅仅要是用Python做的多线程程序。就无法利用多个CPU。
经过一些失败的尝试后,我也一度觉得GIL是无解的。我们甚至把注意力转向了IronPython等无锁Python,可是实际上那样问题可能很多其它。比方我们不熟悉mono,mono也没达到全然成熟的程度。
直到skynet的QQ群里一位朋友介绍了还有一种载入so的方式,事情才有了180度的变化。
方法例如以下:
1、编译Python源代码,编译时加上參数--enable-shared,编译成so动态链接库。
2、找到so,拷贝N份。分别命名为 libpython_1.so, libpython_2.so, ... 等等
3、用C语言。使用linux下的ldfcn库。动态载入这些so库,ldfcn能够保证同名全局变量不冲突。
(C语言源代码。待整理)
(编译注意事项。待整理)
(环境变量设置,待整理)
用简单Py脚本測试。会发现脚本的执行确实是独立的。可是假设用了 import time。则会造成段错误。
原因是用这样的方法。以后import的各种python的库,假设是C语言扩展的,那么就会由于反复而冲突。
解决方法是在编译Python时,增加--enable-time,把time库和python库编译到一起。就能解决问题。(解决方法见后面)
(还有一种备选方案是找到time源代码。在库名后加上数字,也编出N份time_1, time_2... 等等。在脚本里也分别import不同的time库,就可以。)
(2015-9-3注:对这个问题的理解在本系列第六章会有深入的解答。)
因为我们的Python环境禁止在脚本内启动多线程,所以能够增加编译參数--without-threads,这样还能略微提高一点执行效率。
2015-8-26补充:
在编译python时把其它module增加同一个so:
改动 Module/Setup 文件,查找datetime。依照datetime相同的格式写上你要打包的源文件和目标名称。
被凝视的库取消凝视也能够打包。
检查是否打包成功:
用vim之类的文本编辑器,直接打开so文件,搜索keyword。比方datetime,就可以确认你的源代码是否被打包进入so。
(执行的时候注意确认,用python启动的是哪一个so,是系统的还是自己编译的。
建议每次启动都暂时改动LD_LIBRARY_PATH环境变量,避免污染系统环境。)
经过一些失败的尝试后,我也一度觉得GIL是无解的。我们甚至把注意力转向了IronPython等无锁Python,可是实际上那样问题可能很多其它。比方我们不熟悉mono,mono也没达到全然成熟的程度。
直到skynet的QQ群里一位朋友介绍了还有一种载入so的方式,事情才有了180度的变化。
方法例如以下:
1、编译Python源代码,编译时加上參数--enable-shared,编译成so动态链接库。
2、找到so,拷贝N份。分别命名为 libpython_1.so, libpython_2.so, ... 等等
3、用C语言。使用linux下的ldfcn库。动态载入这些so库,ldfcn能够保证同名全局变量不冲突。
(C语言源代码。待整理)
#include <stdio.h> #include "Python.h" #include <dlfcn.h> #include <pthread.h> #define N 5 void* h = { NULL }; void thread( int index ) { void(*py_init)(); int(*is_init)(); PyObject*(*py_import)(char*); PyObject*(*py_getattr_bystr)(PyObject*, char*); PyObject*(*py_call)(PyObject*, PyObject*); py_init = NULL; is_init = NULL; py_import = NULL; py_getattr_bystr = NULL; py_call = NULL; PyObject* mod = NULL; PyObject* func = NULL; PyObject* ret = NULL; py_init = dlsym( h[index], "Py_Initialize" ); is_init = dlsym( h[index], "Py_IsInitialized" ); py_import = dlsym( h[index], "PyImport_ImportModule" ); py_getattr_bystr = dlsym( h[index], "PyObject_GetAttrString" ); py_call = dlsym( h[index], "PyObject_CallObject" ); py_init(); mod = py_import( "hello" ); func = py_getattr_bystr( mod, "output" ); ret = py_call( func, NULL ); return; } int main() { char temp[64]; int i; int ret; pthread_t tid[5] = {0}; for (i=0; i<N; ++i) { sprintf( temp, "libpython/libpython3.4m_%d.so", i+1 ); //h[i] = dlopen( temp, RTLD_NOW | RTLD_DEEPBIND ); h[i] = dlopen( temp, RTLD_NOW ); } for ( i=0; i<N; ++i ) { ret=pthread_create( &tid[i], NULL, (void *)thread, (void*)i ); // 成功返回0。错误返回错误编号 } for ( i=0; i<N; ++i ) { pthread_join( tid[i],NULL ); } return 0; }
(编译注意事项。待整理)
(环境变量设置,待整理)
用简单Py脚本測试。会发现脚本的执行确实是独立的。可是假设用了 import time。则会造成段错误。
原因是用这样的方法。以后import的各种python的库,假设是C语言扩展的,那么就会由于反复而冲突。
解决方法是在编译Python时,增加--enable-time,把time库和python库编译到一起。就能解决问题。(解决方法见后面)
(还有一种备选方案是找到time源代码。在库名后加上数字,也编出N份time_1, time_2... 等等。在脚本里也分别import不同的time库,就可以。)
(2015-9-3注:对这个问题的理解在本系列第六章会有深入的解答。)
因为我们的Python环境禁止在脚本内启动多线程,所以能够增加编译參数--without-threads,这样还能略微提高一点执行效率。
2015-8-26补充:
在编译python时把其它module增加同一个so:
改动 Module/Setup 文件,查找datetime。依照datetime相同的格式写上你要打包的源文件和目标名称。
被凝视的库取消凝视也能够打包。
检查是否打包成功:
用vim之类的文本编辑器,直接打开so文件,搜索keyword。比方datetime,就可以确认你的源代码是否被打包进入so。
(执行的时候注意确认,用python启动的是哪一个so,是系统的还是自己编译的。
建议每次启动都暂时改动LD_LIBRARY_PATH环境变量,避免污染系统环境。)
相关文章推荐
- Python游戏服务器开发日记(二)绕过GIL启动多线程Python环境
- Python游戏server开发日记(一)目标
- Python游戏服务器开发日记(六) 解决GIL难题!——Python再认识
- Python游戏服务器开发日记(一)目标
- 为 Python Server Pages 和 Oracle 构建快速 Web 开发环境
- Python多线程启动http.server
- 为 Python Server Pages 和 Oracle 构建快速 Web 开发环境。
- Coco2d-x android win7 Python 游戏开发环境的搭建
- Python游戏服务器开发日记(八)整体方案改变了……
- Python游戏服务器开发日记(四)scons编译工具、C和C++混合使用
- 为 Python Server Pages 和 Oracle 构建快速 Web 开发环境。
- cocos2d-3.2+python+NDK搭建游戏开发环境
- Python游戏服务器开发日记(七) 关于协程(greenlet)和C语言的思考
- Python游戏服务器开发日记(九)近期问题总结。(打酱油中……)
- 用vs开发android游戏,配置JDK ADT SDK cocos2dx-3.0 python NDK ANT 环境变量
- Python游戏服务器开发日记(五)skynet_messagequeue和skynet_timer
- Python游戏服务器开发日记(三)用greenlet模拟lua coroutine的研究
- Coco2d-x android win7 Python 搭建游戏开发环境
- 成功安装 Visual Studio 2005 并启动开发环境后 FIX: 错误消息: " 包加载失败 "
- Symbian多平台游戏引擎开发日记 2006-6-26