我需要实现 Iterator返回两个值(到目前为止没有异常),但这些值需要并行连续计算/生成,即使未请求迭代器也是如此。
这里是一个例子来解释我需要什么。
def GenerateValues()
#I do the math for value1 in the first thread
#I do the math for value2 in the second thread
return value1 value2
def myIterator()
while 1:
yield GenerateValues()
在这种情况下,value1和 value2仅在调用函数 myIterator 时并行计算/生成。但在我的问题中,计算/生成 value1 需要很长时间和 value2 , 但它也需要很长时间来处理 value1和 value2 .所以当我的软件正在处理value1和 value2 , 我希望它并行计算新的 value1和新value2 .
所以它会是这样的:
def GenerateValues()
#If value1 and value 2 are not computed, then wait.
#I do the math for the new value1 in the first thread without blocking
#I do the math for the new value2 in the second thread without blocking
return value1 value2
def myIterator()
while 1:
yield GenerateValues()
有了这样的配置,新的value1和新value2在 value1 时计算/生成和 value2返回进行处理。
- 够清楚了吗?
- 如果是,我该如何进行同步?
预先感谢您的帮助!
PS:我需要 while 1 ,这一点无需评论。
请您参考如下方法:
不确定我是否完全理解你想要做什么,如果你试图并行计算 value1 和 value2,你可以使用 multiprocessing 或 threading。如果任务受 CPU 限制,我建议使用 multiprocessing,以充分利用您的 CPU 通过使用子进程而不是线程来“回避”全局解释器锁 (GIL)。
这是一个使用多处理的相当直接的例子:
from multiprocessing import Queue, Process
def cal_value1(queue):
# do the job
queue.put({'value1': value1})
def cal_value2(queue):
# do the job
queue.put({'value2': value2})
def GenerateValues()
#If value1 and value 2 are not computed, then wait.
queue = Queue() #
process_1 = Process(target=cal_value1, args=(queue, ))
process_2 = Process(target=cal_value2, args=(queue, ))
process_1.start()
process_2.start() # start both processes
process_1.join()
process_2.join() # wait for both to finish
result = queue.get()
result.update(queue.get()) # get results
return result['value1'], result['value2']
附言您可以轻松地使用 threading.Thread 和 Queue.Queue 来替换 multiprocessing.Process 和 multiprocessing.Queue 如果你想。
编辑: 现在让 cal_value1 和 cal_value2 长时间运行的进程,您可能希望在脚本的开头启动这 2 个进程。
from multiprocessing import Queue, Process
def cal_value1(tasks, results):
while True:
task = tasks.get() # this will block until a new task coming in
# calculate value1
results.put({'value1': value1})
def cal_value2(tasks, results):
while True:
task = tasks.get() # this will block until a new task coming in
# calculate value2
results.put({'value2': value2})
def main():
cal_value1_tasks, cal_value2_tasks, results = Queue(), Queue(), Queue()
process_1 = Process(target=cal_value1, args=(cal_value1_tasks, results, ))
process_2 = Process(target=cal_value2, args=(cal_value2_tasks, results, ))
process_1.start()
process_2.start()
cal_value1_tasks.put('cal_value1')
cal_value2_tasks.put('cal_value2') # Start to calculate the first pair
values = GenerateValues(cal_value1_tasks, cal_value2_tasks, results)
def GenerateValues(cal_value1_tasks, cal_value2_tasks, results):
values = results.get() # get results
values.update(queue.get()) # notice that it'll block until both value1 and value 2 calculated
cal_value1_tasks.put('cal_value1')
cal_value2_tasks.put('cal_value2') # before returning, start to calculate the next round of value1 and value2
return values['value1'], values['value2]
