python加速

python中的进程、线程和协程

  1. 多线程:由于GIL的存在,一个时刻只能有一个线程有解释器的控制权,所以多线程对于CPU密集型程序没有什么帮助,对IO密集型有帮助

  2. 多进程:每个进程有自己的解释器和内存空间,能对CPU密集型程序加速。缺点是切换进程的开销很大。

  3. 协程:用户级线程,在单线程中实现并发。相比多线程省去线程切换开销,对IO密集型有用。因为公用一个线程,所以对CPU密集型影响不大。

    1. 进程和线程是抢占式多任务,都是由调度程序决定跑哪一个线程(进程),用户不能确定顺序

    2. 协程是协作式多任务,协程中用户确定调用逻辑。协程切换完全在用户空间进行,协程切换只涉及基本的CPU上下文切换。

    3. 协程单线程就可以实现高并发,单核CPU可支持上万的协程,适合用于高并发处理,尤其是在应用在网络爬虫中。可以用于IO的多路复用。

    4. 协程的缺点:本质上是单线程,不能直接用多核,如果要用多核CPU,需要多进程+协程

    5. 第三方的gevent为Python提供了比较完善的协程支持

      1. 当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成会收到通知,再在适当的时候切换回来继续执行。

      2. 由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。

python利用多核CPU的方法

  1. 使用多进程。缺点是进程间内存地址空间独立,通信要比多线程麻烦很多

  2. C代码编写计算密集型程序,通过拓展方式写入python脚本(NumPy模块),在拓展中可以用C的原生线程,不会用到GIL,比较麻烦。

  3. 使用ctypes。它可以让Python直接调用C动态库的导出函数。ctypes会在调用C函数前释放GIL

    1. 用C语言写一个函数,编译生成动态库lib.so

    2. 在python代码中使用ctypes来load这个动态库并执行

目前提到过的加速方法

  1. 减少过程中新建矩阵对象的数量

  2. 求解器使用C++写

  3. 多进程改写


本文章使用limfx的vscode插件快速发布