为了账号安全,请及时绑定邮箱和手机立即绑定

python3多进程共享numpy数组(只读)

python3多进程共享numpy数组(只读)

慕仙森 2021-11-02 09:53:11
我不确定这个标题是否适合我的情况:我想分享 numpy 数组的原因是它可能是我案例的潜在解决方案之一,但如果您有其他解决方案也不错。我的任务:我需要用multiprocessing实现一个迭代算法,而这些进程中的每一个都需要有一个数据副本(这个数据很大,并且是只读的,并且在迭代算法期间不会改变)。我写了一些伪代码来演示我的想法:import multiprocessingdef worker_func(data, args):    # do sth...    return resdef compute(data, process_num, niter):    data    result = []    args = init()    for iter in range(niter):        args_chunk = split_args(args, process_num)        pool = multiprocessing.Pool()        for i in range(process_num):            result.append(pool.apply_async(worker_func,(data, args_chunk[i])))        pool.close()        pool.join()        # aggregate result and update args        for res in result:            args = update_args(res.get())if __name__ == "__main__":    compute(data, 4, 100)问题是在每次迭代中,我都必须将数据传递给子进程,这非常耗时。我想出了两个潜在的解决方案:在进程之间共享数据(它是 ndarray),这就是这个问题的标题。保持子进程处于活动状态,例如守护进程或其他东西......并等待调用。通过这样做,我只需要在一开始就传递数据。那么,有没有办法在进程之间共享一个只读的 numpy 数组?或者,如果您很好地实施了解决方案 2,它也可以工作。
查看完整描述

2 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

如果您绝对必须使用 Python 多处理,那么您可以使用 Python 多处理和Arrow 的 Plasma 对象存储来将对象存储在共享内存中并从每个工作人员访问它。请参阅此示例,它使用 Pandas 数据帧而不是 numpy 数组执行相同的操作。


如果您不是绝对需要使用 Python 多处理,您可以使用Ray更轻松地做到这一点。Ray 的一个优点是它不仅可以处理数组,还可以处理包含数组的 Python 对象。


在幕后,Ray 使用Apache Arrow序列化 Python 对象,这是一种零拷贝数据布局,并将结果存储在Arrow 的 Plasma 对象存储中。这允许工作任务对对象进行只读访问,而无需创建自己的副本。您可以阅读有关其工作原理的更多信息。


这是您运行的示例的修改版本。


import numpy as np

import ray


ray.init()


@ray.remote

def worker_func(data, i):

    # Do work. This function will have read-only access to

    # the data array.

    return 0


data = np.zeros(10**7)

# Store the large array in shared memory once so that it can be accessed

# by the worker tasks without creating copies.

data_id = ray.put(data)


# Run worker_func 10 times in parallel. This will not create any copies

# of the array. The tasks will run in separate processes.

result_ids = []

for i in range(10):

    result_ids.append(worker_func.remote(data_id, i))


# Get the results.

results = ray.get(result_ids)

请注意,如果我们省略该行data_id = ray.put(data)而改为调用worker_func.remote(data, i),则data数组将在每次函数调用时存储在共享内存中,这将是低效的。通过第一次调用ray.put,我们可以将对象一次存储在对象存储中。


查看完整回答
反对 回复 2021-11-02
  • 2 回答
  • 0 关注
  • 451 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号