总结一下,对于单核系统来说,GIL是一个相当不错的设计(Python基本上将线程处理/调度交给操作系统)。但是,在多核系统上,这可能会导致IO密集型线程受到CPU密集型线程的严重阻塞,造成上下文切换的开销,Ctrl-C问题[*]等等。
所以,既然GIL限制我们基本上只能在一个CPU上执行Python程序,我的想法是为什么不接受这一点,并简单地使用Linux上的taskset命令将程序的亲和性设置为系统上的某个核心/CPU(尤其是在多核系统上运行多个Python应用程序的情况下)?
所以,我的问题是这样的:有人在Linux上使用过taskset来运行Python应用程序吗(尤其是在Linux系统上运行多个应用程序,以便将多个核心与一个或两个绑定到特定核心的Python应用程序一起使用),如果有的话,结果如何?这样做是否值得?对于某些工作负载,会使情况变得更糟吗?我计划这样做并进行测试(基本上看看程序运行需要更长时间还是更短时间),但我很想听听其他人的经验。
补充说明:David Beazley(在链接视频中发表演讲的那个人)指出,一些C/C++扩展手动释放GIL锁,如果这些扩展针对多核进行了优化(例如科学或数值数据分析等),那么它们将无法享受到多核的好处,而是被限制在单个核心上(从而可能显著减慢程序的运行速度)。另一方面,如果您不使用此类扩展程序。
我不使用多进程模块的原因是(在这种情况下),程序的一部分严重依赖网络I/O(HTTP请求),因此拥有一个工作线程池是提高性能的绝佳方式,因为一个线程发出一个HTTP请求,然后由于等待I/O而释放GIL,另一个线程可以执行其任务,所以程序的这部分可以轻松运行100多个线程而不会对CPU造成太大负担,并且让我真正利用可用的网络带宽。至于无栈Python等,我对重写程序或替换Python堆栈并不过于感兴趣(可用性也是一个问题)。
[*] 只有主线程能接收信号,所以如果发送ctrl-C,Python解释器基本上会尝试让主线程运行以处理信号,但由于它不能直接控制哪个线程运行(这由操作系统决定),它基本上告诉操作系统不断切换线程,直到最终达到主线程(如果你运气不好可能需要一段时间)。