如何使 Python 生成器异步执行?
How to make a Python generator execution asynchronous?
我有一段代码如下所示:
def generator():
while True:
result = very_long_computation()
yield result
def caller():
g = generator()
for i in range(n):
element = next(g)
another_very_long_computation()
基本上,我想尽可能地重叠 very_long_computation()
和 another_very_long_computation()
的执行。
有没有简单的方法让生成器异步?我希望生成器在生成 result
之后立即开始计算 while 循环的下一次迭代,这样(理想情况下)下一个 result
就可以在后续 [=16] 之前生成=] 调用 caller()
.
没有简单的方法,特别是因为您有 very_long_computation
和 another_very_long_computation
而不是 very_slow_io
。即使您将 generator
移动到它自己的线程中,您也会受到 CPython 的全局解释器锁的限制,从而无法获得任何性能优势。
您可以将工作转移到工作进程中,但 multiprocessing
模块并不是它喜欢伪装的 threading
的直接替代品。它充满了奇怪的复制语义、不直观的限制和依赖于平台的行为,以及大量的通信开销。
如果您在计算的同时得到了 I/O,那么将生成器的工作推到它自己的线程中以至少在 I/O 期间完成一些工作是相当简单的:
from queue import Queue
import threading
def worker(queue, n):
gen = generator()
for i in range(n):
queue.put(next(gen))
def caller():
queue = Queue()
worker_thread = threading.Thread(worker, args=(queue, n))
worker_thread.start()
for i in range(n):
element = queue.get()
another_very_long_computation()
我有一段代码如下所示:
def generator():
while True:
result = very_long_computation()
yield result
def caller():
g = generator()
for i in range(n):
element = next(g)
another_very_long_computation()
基本上,我想尽可能地重叠 very_long_computation()
和 another_very_long_computation()
的执行。
有没有简单的方法让生成器异步?我希望生成器在生成 result
之后立即开始计算 while 循环的下一次迭代,这样(理想情况下)下一个 result
就可以在后续 [=16] 之前生成=] 调用 caller()
.
没有简单的方法,特别是因为您有 very_long_computation
和 another_very_long_computation
而不是 very_slow_io
。即使您将 generator
移动到它自己的线程中,您也会受到 CPython 的全局解释器锁的限制,从而无法获得任何性能优势。
您可以将工作转移到工作进程中,但 multiprocessing
模块并不是它喜欢伪装的 threading
的直接替代品。它充满了奇怪的复制语义、不直观的限制和依赖于平台的行为,以及大量的通信开销。
如果您在计算的同时得到了 I/O,那么将生成器的工作推到它自己的线程中以至少在 I/O 期间完成一些工作是相当简单的:
from queue import Queue
import threading
def worker(queue, n):
gen = generator()
for i in range(n):
queue.put(next(gen))
def caller():
queue = Queue()
worker_thread = threading.Thread(worker, args=(queue, n))
worker_thread.start()
for i in range(n):
element = queue.get()
another_very_long_computation()