我不确定这个标题是否适合我的情况:我想共享numpy数组的原因是它可能是我的案例的潜在解决方案之一,但是如果您还有其他解决方案,也可以很好。
我的任务:我需要通过 multiprocessing 实现迭代算法,而每个流程都需要有一个数据副本(此数据很大,而< strong>只读,并且在迭代算法中不会更改)。
我写了一些伪代码来证明我的想法:
import multiprocessing
def worker_func(data, args):
# do sth...
return res
def 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)
问题在于每次迭代,我必须将数据传递给子流程,这非常耗时。
我提出了两种可能的解决方案:
那么,有什么方法可以在进程之间共享一个只读的numpy数组?或者,如果您有解决方案2的良好实现,它也可以工作。
谢谢。
答案 0 :(得分:1)
如果绝对必须使用Python多重处理,则可以将Python多重处理与Arrow's Plasma object store一起使用,以将对象存储在共享内存中并从每个工作线程访问它。参见this example,该示例使用Pandas数据框而不是numpy数组执行相同的操作。
如果您绝对不需要使用Python多处理程序,则可以使用Ray轻松地完成此操作。 Ray的优点之一是,它不仅可以与数组一起使用,而且还可以与包含数组的Python对象一起使用。
在后台,Ray使用Apache Arrow(这是零拷贝的数据布局)序列化Python对象,并将结果存储在Arrow's Plasma object store中。这允许工作任务对对象具有只读访问权限,而无需创建自己的副本。您可以阅读有关how this works的更多信息。
这是您示例运行的修改版。
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
,我们可以一次将对象存储在对象存储中。
答案 1 :(得分:0)
从概念上来说,使用mmap
是一种标准方法。
这样,可以通过多个进程从映射的内存中检索信息
对mmap的基本了解:
https://en.wikipedia.org/wiki/Mmap
Python具有“ mmap”模块(import mmap
)
python标准的文档和一些示例在下面的链接中