我能在单核机器上运行多进程Python程序吗?

21

这更多是一个理论问题。我有一台单核机器,虽然它很强大,但只有一个核心。现在我有两个选择:

  1. 多线程:据我所知,即使我有多个核心,由于GIL的限制,我也无法在我的机器上利用多个核心。因此,在这种情况下,没有任何区别。

  2. 多进程:这是我有疑问的地方。我能否在单核机器上进行多进程操作?或者每次都必须检查机器中可用的核心,然后运行完全相同或较少数量的进程?

有人能否指导一下我关于多进程和机器核心之间的关系。

我知道这是一个理论问题,但我的概念不是很清楚。


你可以自己回答这个问题:检查你的系统上运行的程序数量,然后将其与核心数进行比较。 - Klaus D.
3个回答

14

这是一个大课题,但以下是一些提示。

  • 将线程视为共享相同地址空间并可以访问相同内存的进程。通信通过共享变量完成。多个线程可以在同一进程中运行。
  • 进程(在此上下文中,粗略地说)具有自己的私有数据,如果两个进程想要通信,则必须更加明确地进行通信。
  • 当您编写的程序瓶颈是CPU周期时,无论是线程还是进程都不会在单核机器上提供速度提升。
  • 进程和线程仍然对多任务处理(快速切换(子)程序)很有用 - 这就是您的操作系统所做的,因为它运行的进程比您有的核心要多得多。
  • 即使在单核心机器上执行的任务受I/O限制时,进程和线程(甚至协程!)也可以为您提供相当大的速度提升 - 想想从网络获取数据。例如,另一个进程或线程可以启动下一个网络操作,而不是主动等待数据被发送或到达。
  • 由于线程开销较低,因此在不需要显式封装的情况下,线程优于进程。对于大多数CPU绑定并发问题,特别是大量的“embarassingly parallel”问题,生成多个进程比您拥有的处理器更没有意义。
  • Python GIL防止同一进程中的两个线程并行运行,即多个核心同时执行指令。
  • 因此,在Python中,线程对于加速CPU绑定任务相对无用,但对于I/O绑定任务仍然非常有用,因为阻塞操作(例如等待网络数据)会释放GIL,以便另一个线程在等待时可以运行。
  • 如果您有多个处理器,则可以通过生成多个进程来实现真正的并行性,尽管存在GIL。这仅对CPU绑定任务值得,并且通常必须考虑生成进程的开销和进程之间的通信成本。

可能我没有清楚地表达我的问题。由于我只有一个核心,我启动了3个计算密集型进程,操作系统必须在它们之间进行上下文切换。因此,在一个核心上并行运行3个进程是不可能实现的。请告诉我我的理解是否正确。 - Subhayan Bhattacharya
1
@user1867151,你理解得很正确。并发处理是指同时处理多个任务,并通过上下文切换来实现;而并行处理则是指在同一时刻执行多个任务。要实现真正的并行处理,需要不止一个处理器。 - timgeb

2

在单核系统中,您可以同时使用多线程和多进程。

GIL限制了纯Python在计算密集型任务中使用多线程的效用,无论底层架构如何。对于I/O密集型任务,它们表现良好。如果它们没有任何用处,它们可能根本不会被实现。

对于纯Python软件,多进程始终是并行计算的更安全选择。当然,与多线程相比,多个进程更昂贵(因为进程不像线程那样共享内存;另外,进程与线程相比具有稍高的开销)。

然而,在单处理器机器上,对于计算密集型任务,多进程(和多线程)几乎不会带来额外的速度,并且它们实际上甚至会使您的速度变慢一些。但是,如果操作系统支持它们(这对于桌面,工作站,集群等非常普遍,但对于嵌入式系统可能不太常见),它们允许您有效地同时运行多个I/O密集型程序。

长话短说,这有点取决于您正在做什么...


1

multiprocessing 模块基本上会生成多个 Python 解释器实例,因此不必担心 GIL 问题。

如果您以前使用过 threading 模块,则 multiprocessing 使用相同的 API。


您似乎对多进程、线程(您将其称为多线程)和X核处理器感到困惑。

  • 无论如何,当您启动Python (CPython实现)时,它只会使用处理器的一个核心。
  • 线程是在脚本的不同组件之间分配负载。假设您必须与外部API进行交互,您的脚本必须等待通信完成才能继续下一步。如果您正在进行多个类似的调用,则需要花费线性时间。而如果您使用线程,则可以同时执行这些调用。

另请参阅: Python的PyPy实现


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