是否有一种简单的 Python 3 方法可以像 Java 那样制作并行 for 循环?

Is there a simple Python 3 way of making parallel for loop like in Java?

我来自Java。在 Java 8 及更高版本中,我们有并发性 API(执行器服务、倒计时锁存器、循环屏障、并行流 API)。 Python3中有没有像这样简单的API?我只发现了很多丑陋的代码,每个人都在重新发明轮子,比如在硬编码的特定 dict 或带有自定义代码的列表上进行 fork join 操作。

假设我有一个包含 50 000 个元素的字典,它包含 group_id 个整数。我想统计每组有多少个元素

类似这样的东西,但我想让它变得漂亮、干净和平行:

import collections

dataset_dict = collections.defaultdict(int)

for img, group_id in dataset:
    dataset_dict[classes[group_id]] += 1

print(dataset_dict)

我发现最好的是 Python 3 中的 Ray 库,但是 API 的级别非常低,无法与其他现代语言相提并论。随着 Python 中 lambdas 和 PyTorch / Keras 机器学习的繁荣,Typescript 的进步和自 Java 8 以来的大修,我真的需要 Python 3.

中类似的东西

你能为上面的代码提供一些简单的例子吗?我用 Ray 尝试了一些东西,这似乎是最简单的。但问题是在共享变量中写入增量。也许你知道更好、更现代的 API for Python 3.

预期的行为是 50 000 个元素将按 CPU 数量拆分。每个线程将汇总组计数,然后将结果加入最终结果。我认为在这种情况下它可能只是一个简单的 Fork Join 池。我想要一个完美干净的代码,易于阅读。因此,您只需阅读代码,就会得到 "aha" 的感觉,它很简单,但也很聪明,因为美在于简单。

Python 和 Java 之间的一个基本区别是 Python 有一个 Global Interpreter Lock。这使得以与 Java 相同的方式实现低级线程变得有点困难。

在Python中,并行通常是通过多个进程实现的。 Multiprocessing 是内置库,它通常包装生成多个进程和共享内存对象的过程。请注意,还有一个 asyncio 库提供协程但不提供真正的并行性(用户级协作多任务)

Ray 是一个完整的分布式系统,因此它可以帮助 parallelize/distribute python 跨单台机器或整个集群的核心进行编码。对于 Ray,您可以使用 Parallel Iterator instead of a list, and wrap your dataset_dict in an actor。它可能看起来像:

dataset_iter = from_items(dataset)
dataset_iter.for_each(lambda x: ray.get(dataset_dict.increment.remote(x)))
# This line starts the processing
list(dataset_iter.gather_async())

dataset_dict看起来像

import collections
@ray.remote
class Counter:
 def __init__(self):
  self.counter = collections.Counter()

 def increment(self, key):
  self.counter[key] += 1

dataset_dict = Counter.remote()