【发布时间】:2019-11-06 12:07:55
【问题描述】:
我有一个非常大的(只读)数据数组,希望由多个进程并行处理。
我喜欢 Pool.map 函数,并希望使用它来并行计算该数据上的函数。
我看到可以使用Value 或Array 类在进程之间使用共享内存数据。但是当我尝试使用它时,我会在使用 Pool.map 函数时得到一个RuntimeError: 'SynchronizedString objects should only be shared between processes through inheritance:
这是我正在尝试做的一个简化示例:
from sys import stdin
from multiprocessing import Pool, Array
def count_it( arr, key ):
count = 0
for c in arr:
if c == key:
count += 1
return count
if __name__ == '__main__':
testData = "abcabcs bsdfsdf gdfg dffdgdfg sdfsdfsd sdfdsfsdf"
# want to share it using shared memory
toShare = Array('c', testData)
# this works
print count_it( toShare, "a" )
pool = Pool()
# RuntimeError here
print pool.map( count_it, [(toShare,key) for key in ["a", "b", "s", "d"]] )
谁能告诉我我在这里做错了什么?
所以我想做的是在进程池中创建进程后将有关新创建的共享内存分配数组的信息传递给进程。
【问题讨论】:
-
不幸的是,这是不可能的。根据 mp 文档推荐的方法是使用继承(在 fork 平台上)。对于您在此处拥有的只读数据,通常会使用全局,但可以使用共享数组进行读/写通信。分叉很便宜,因此您可以在收到数据时重新创建池,然后再关闭它。不幸的是,在 Windows 上这是不可能的 - 解决方法是使用共享内存数组(即使在只读情况下),但这只能在进程创建时传递给子进程(我想它们需要添加到访问列表中...
-
对于共享内存段,并且除了在子进程启动时不实现此逻辑)。您可以像我展示的那样在 Pool 启动时传递共享数据数组,或者以类似的方式传递给 Process。您不能将共享内存数组传递给打开的池 - 您必须在内存之后创建池。解决此问题的简单方法包括分配最大大小的缓冲区,或者在启动池之前知道所需大小时仅分配数组。如果你保持全局变量在 Windows 上也不会太贵 - 全局变量会自动...
-
腌制并发送到子进程 - 这就是为什么我建议在开始时制作一个足够大小的缓冲区(希望你的全局变量数量很小),然后池更好。我花时间真诚地理解和解决你的问题 - 在你编辑你的问题之前 - 所以虽然我理解你是否想让它运行,但我希望最后你会考虑接受我的回答,如果没有什么实质性不同/更好的结果沿着。
-
我仔细查看了源代码,并且可以腌制有关共享内存的信息(需要将有关它的信息传递给 Windows 上的客户端进程),但该代码只有一个断言在进程生成期间运行。我想知道为什么会这样。
标签: python multiprocessing shared-memory pool