栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

利用“写时复制”功能将数据复制到Multiprocessing.Pool()工作进程

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

利用“写时复制”功能将数据复制到Multiprocessing.Pool()工作进程

发送到

pool.map
(以及相关方法)的所有内容实际上都没有使用共享的写时复制资源。这些值被“
pickled”(Python的序列化机制)
,通过管道发送到工作进程,然后在其中取消pick,从而从头开始在子进程中重建对象。因此,在这种情况下,每个孩子最终都会得到原始数据的写时复制版本(它从未使用过,因为被告知要使用通过IPC发送的副本),并且个人重新获得了原始数据。在孩子中重建,不共享。

如果要利用分叉的写时复制优势,则不能通过管道发送数据(或引用数据的对象)。您必须将它们存储在可以通过访问其自己的全局变量从孩子那里找到的位置。因此,例如:

import timefrom multiprocessing import Poolimport numpy as npclass MyClass(object):    def __init__(self):        self.myAttribute = np.zeros(100000000) # basically a big memory struct    def my_multithreaded_analysis(self):        arg_lists = list(range(10))  # Don't pass self        pool = Pool(processes=10)        result = pool.map(call_method, arg_lists)        print result    def analyze(self, i):        time.sleep(10)        return i ** 2def call_method(i):    # Implicitly use global copy of my_instance, not one passed as an argument    return my_instance.analyze(i)# Constructed globally and unconditionally, so the instance exists# prior to forking in commonly accessible locationmy_instance = MyClass()if __name__ == '__main__':    my_instance.my_multithreaded_analysis()

通过不传递

self
,可以避免进行复制,而仅使用写时复制映射到子对象的单个全局对象。如果需要多个对象,则可以在创建池之前对对象的实例进行全局
list
dict
映射,然后将可以将对象作为参数的一部分的索引或键传递给
pool.map
。然后,worker函数使用索引/键(必须通过IPC对其进行腌制并将其发送给子代)在全局dict(还包括写时复制映射)中查找值(写时复制映射),因此,您可以复制便宜的信息以在孩子中查找昂贵的数据而不进行复制。

如果对象很小,即使您不对其进行写操作,它们也将最终被复制。
CPython被引用计数,并且引用计数出现在公共对象标头中,并且仅通过引用该对象就可以不断更新,即使它是逻辑上不变的引用。因此,将写入并复制小对象(以及分配在同一页内存中的所有其他对象)。对于大型对象(一亿个元素的numpy数组),只要您不对其进行写操作,大部分内容将保持共享状态,因为标头仅占据许多页面之一



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/641107.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号