Python是否是并发编程的一个严肃选项?

6

我正在考虑开始学习Python,但在投入更多时间之前有一个顾虑。让我将其表述为一个陈述,后面跟着其他人可以评论的问题,因为陈述中的假设可能无效:

我已经了解了GIL,并且普遍认为,如果您需要使用Python进行并发解决方案,最好的方法是派生一个新进程以避免GIL。

我的担忧是,如果我有一个问题,希望将其分成N * 2个部分分配到N个处理器上(例如,假设我有一台运行*nix操作系统的单个服务器,有8个核心),那么我将会在进程之间而不是线程之间产生上下文切换开销,这更加昂贵,这将限制性能。

我提出这个问题是因为还有其他编程语言声称在这种情况下表现优异,我想知道Python是否适用于这个领域。


7
在很多操作系统上,进程和线程是相同的东西。在进程之间切换的代价不比在线程之间切换更大。无论如何,如果上下文切换太频繁会影响性能,这要么意味着你有太多线程并且它们互相竞争CPU,要么是你的线程之间依赖性过强。 - Glenn Maynard
如果它对函数式编程有更好的支持(像是良好的lambda表达式...),那么它将更适合于多线程编程,我个人认为。 - Gordon Gustafson
3
有"def"语句,可以使用它们。 "lambda"语法只是定义函数某些特殊情况的简写,函数对象上的特殊属性"__name__"是"def"和"lambda"之间最大的区别。 - Roger Pate
@Glenn:虽然进程上下文切换可能不比线程更昂贵,但是两个进程之间的通信速度通常比两个线程之间的通信速度慢,内存工作集通常更高,因此内存缓存的效果会降低。在许多情况下,这些因素对性能有重大影响。 - Kylotan
7个回答

15

multiprocessing 可以避开 GIL,但它也引入了它自己的问题,比如进程间通信。


8

Python在CPU密集型并发编程方面表现不佳。GIL会使你的程序运行得像是在单个核心上运行,甚至更糟。即使是Unladen Swallow(引自他们的项目计划)也可能无法完全解决这个问题:“我们对完全消除GIL的机会不再那么乐观”。

正如你所说,其他语言声称在并发编程方面更好。例如,Haskell内置了编写并发应用程序的功能。你也可以尝试使用带有OpenMP的C++,我认为这使得并行化非常简单。

如果您的应用程序是I/O绑定的,则Python可能是一个严肃的解决方案,因为在执行阻塞调用时通常会释放GIL。


好的,谢谢AndiDog,很有趣。Glen Maynard - 我也注意到你的答案。我认为我可以将它作为perl的继任者来学习,因为我的组织在大多数服务器上都提供python并且它似乎表达能力很强。不过我可能不会花费太多时间学习其细节,而是会把时间花在更适合扩展的函数式语言上,比如haskell / erlang。 - Ben Fitzgerald
1
如果你非常需要原始的CPU性能,高级脚本语言往往不是一个正确的选择。 - Glenn Maynard
如果有Nvidia GPU,想了解Pycuda的情况,您感兴趣吗? - MuneshSingh

3

根据我的有限经验,“上下文切换成本”被高估为性能限制。

I/O带宽和内存是最常见的限制因素。Python的I/O与许多其他语言相当,因为它直接使用标准C库。

您实际的问题可能并不典型。然而,许多问题在多处理模式下表现得非常出色,因为它们实际上是I/O绑定的。通常是文件系统、网页读取或数据库操作在上下文切换之前就限制了性能。


你特别提到使用*nix - 在这种情况下,你应该没有问题。 显然,在Windows上,上下文切换成本很小,是一个更大的问题。 我经常在系统上运行1000多个进程(当然不全是Python,但这不应该有影响)而没有任何问题。当然,我应该限定上面的观点,它是在无头Linux系统上,配置为服务器。 没有X11,Gnome,KDE等。 - CyberFonic

3
一个非常简单的答案:Golang。

1

如果你正在考虑学习Python来解决这个问题,我可能建议你去看看Erlang。它对非常轻量级的进程有极好的支持,并且具有内置的进程间通信原语。

当然,并不是要阻止你学习Python,只是建议在这个特定任务上可能有更好的工具可供选择。


1
此外,如果您正在寻找Python进程之间的对象共享,我建议您查看此问题中Alex的答案。

1

编写适用于多个进程的代码并不是一项容易的任务。

但是,如果您首先从这种方式开始思考,最终,如果一个机器不够用,扩展会更容易...线程无法跨越多台机器使用...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接