多线程:由于GIL的存在,一个时刻只能有一个线程有解释器的控制权,所以多线程对于CPU密集型程序没有什么帮助,对IO密集型有帮助
多进程:每个进程有自己的解释器和内存空间,能对CPU密集型程序加速。缺点是切换进程的开销很大。
协程:用户级线程,在单线程中实现并发。相比多线程省去线程切换开销,对IO密集型有用。因为公用一个线程,所以对CPU密集型影响不大。
进程和线程是抢占式多任务,都是由调度程序决定跑哪一个线程(进程),用户不能确定顺序
协程是协作式多任务,协程中用户确定调用逻辑。协程切换完全在用户空间进行,协程切换只涉及基本的CPU上下文切换。
协程单线程就可以实现高并发,单核CPU可支持上万的协程,适合用于高并发处理,尤其是在应用在网络爬虫中。可以用于IO的多路复用。
协程的缺点:本质上是单线程,不能直接用多核,如果要用多核CPU,需要多进程+协程
第三方的gevent为Python提供了比较完善的协程支持
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成会收到通知,再在适当的时候切换回来继续执行。
由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
使用多进程。缺点是进程间内存地址空间独立,通信要比多线程麻烦很多
C代码编写计算密集型程序,通过拓展方式写入python脚本(NumPy模块),在拓展中可以用C的原生线程,不会用到GIL,比较麻烦。
使用ctypes。它可以让Python直接调用C动态库的导出函数。ctypes会在调用C函数前释放GIL
用C语言写一个函数,编译生成动态库lib.so
在python代码中使用ctypes来load这个动态库并执行
减少过程中新建矩阵对象的数量
求解器使用C++写
多进程改写
本文章使用limfx的vscode插件快速发布