Python中的并行性

27 投票
5 回答
15568 浏览
提问于 2025-04-15 23:38

在Python中,有哪些方法可以实现并行处理呢?我想对一些非常大的数据进行大量的计算,并希望能够并行处理。因为我之前是做C语言的,所以我对并行处理有三种了解:

  1. 消息传递进程,可能分布在一个集群上,比如说MPI
  2. 显式共享内存的并行处理,可以使用pthreads或者fork()pipe()等。
  3. 隐式共享内存的并行处理,使用OpenMP

选择使用哪种方法其实是一个权衡的过程。

在Python中,有哪些可用的方法,它们各自的特点是什么?有没有可以集群使用的MPI克隆?实现共享内存并行处理的推荐方式是什么?我听说过关于GIL的问题,还有关于tasklets的提及。

总之,在我选择不同的并行处理策略之前,我需要了解哪些关于Python的并行处理方法的信息呢?

5 个回答

5

Ray 是一个优雅且快速的库,可以用来实现这个功能。

将 Python 函数并行化的最基本方法是使用 @ray.remote 这个装饰器来声明一个函数。这样就可以异步调用这个函数了。

import ray
import time

# Start the Ray processes (e.g., a scheduler and shared-memory object store).
ray.init(num_cpus=8)

@ray.remote
def f():
    time.sleep(1)

# This should take one second assuming you have at least 4 cores.
ray.get([f.remote() for _ in range(4)])

你还可以通过使用 @ray.remote 装饰器来并行化有状态的计算,这种方法叫做 演员模型

# This assumes you already ran 'import ray' and 'ray.init()'.

import time

@ray.remote
class Counter(object):
    def __init__(self):
        self.x = 0

    def inc(self):
        self.x += 1

    def get_counter(self):
        return self.x

# Create two actors which will operate in parallel.
counter1 = Counter.remote()
counter2 = Counter.remote()

@ray.remote
def update_counters(counter1, counter2):
    for _ in range(1000):
        time.sleep(0.25)
        counter1.inc.remote()
        counter2.inc.remote()

# Start three tasks that update the counters in the background also in parallel.
update_counters.remote(counter1, counter2)
update_counters.remote(counter1, counter2)
update_counters.remote(counter1, counter2)

# Check the counter values.
for _ in range(5):
    counter1_val = ray.get(counter1.get_counter.remote())
    counter2_val = ray.get(counter2.get_counter.remote())
    print("Counter1: {}, Counter2: {}".format(counter1_val, counter2_val))
    time.sleep(1)

multiprocessing 模块相比,它有很多优点:

  • 同样的代码可以在单个多核机器上运行,也可以在大型集群上运行。
  • 在同一台机器上,进程之间可以高效地共享数据,使用的是 共享内存和高效序列化
  • 你可以并行化 Python 函数(使用任务)和 Python 类(使用演员模型)
  • 错误信息的传播也很友好。

Ray 是一个我参与开发的框架。

6

新的 (2.6) multiprocessing 模块是个不错的选择。它使用子进程,这样就能绕过 GIL 问题。这个模块还简化了一些本地和远程运行的问题,所以你可以稍后再决定是把代码放在本地运行还是分散在多个计算机上。上面我链接的文档内容有点多,但应该能为你入门提供一个很好的基础。

18

一般来说,你在说的是一种需要大量计算的情况,这种情况对CPU的要求很高。而这并不是Python擅长的领域。历史上,Python在多进程方面也表现得不太好。

在主流的Python解释器中,线程的使用受到一个让人头疼的全局锁的限制。新的多进程 API绕过了这个问题,提供了一种工作池的抽象,里面有管道和队列等工具。

如果你需要写性能要求很高的代码,可以选择用C语言或者Cython来实现,然后用Python来把这些代码连接起来。

撰写回答