假设我有一个无法被腌制的对象,但我在 Linux 上运行我的代码,并希望利用 fork 的优势。
如果我从解释器运行我的代码,它看起来像这样:
from multiprocessing.pool import Pool
# large object that takes time to calculate - and is not picklable
large_obj = get_large_obj()
def some_func(c):
return large_obj.do_something_with_int(c)
pool = Pool(64)
pool.map(some_func,[1,2,3,4,5,6,7,.....,10000])
如果我在 Linux 中运行它,这将起作用,因为所有进程都会">知道"large_obj
我的问题是 - 如果我想在类中或仅在方法中拥有此代码片段,它将不起作用,因为它将无法腌制我的函数,因为它将是一个未绑定的方法。
我不想使用不同的进程池库(假设loky
(,因为我的大对象是不可拾取的,即使使用例如cloudpickle
(或dill
(。
而且我不想为每个新进程重新计算大对象。我只想计算一次并在pool
内使用它.
有什么解决方案吗?
简而言之,您已经进入了[TIME]
成本与[SPACE]
成本(避免复制副本(的斗争。
在这个全局视图中,与泡菜相关的阶段(这里是标准 python 方式的障碍,进程实例化如何发生,而不是解决问题本身(并不重要。
避免泡菜/复制只是意味着你必须为另一种形式的并发控制付费,而不是">共享"(不可复制(资源 -large_obj
类包装器。
问:有什么解决方案吗?
是的。
一个可能的解决方案可能是设计并开始运行一个足够智能的分布式计算系统架构,其中large_obj
被计算一次,它的包装类可以并发(不是真正的[PARALLEL]
操作(响应">远程"进程的请求(进程被共置在同一主机上或分布在全球(。
为了实现目标,我将开始使用正确调整的 ZeroMQ"中介"基础架构,其中所有传输类{ inproc:// | ipc:// | tipc:// | tcp:// | norm:// | pgm:// | epgm:// | vmci:// }
可以并且可以在同一基础架构中共存,从而允许计算代理同时位于紧密托管区域内(在同一主机上,需要最大接近和最小延迟(和/或跨互连分布式代理的广泛网络(在远程主机上, 其中性能扩展需要比单个本地主机平台所能提供的更多的处理能力(。
生成的模式将根据需要利用[SPACE]
尽可能多的">轻量级"ZeroMQ配备的进程(处理代理(,在任何形式的并发Pool
内运行(其中实际的硬件和/或网格计算资源仍然限制了可能的真实[PARALLEL]
代码执行的范围,因此">公正"[CONCURRENT]
代码执行在严格的计算机科学学科方面更合适(。每个这样的进程实例可以独立存在,并临时向"远程共享服务代理"(该代理确实拥有large_obj
的唯一实例(提交请求,包括所有需要的方法,包括 ZeroMQ 通信处理设施,其中来自远程代理的传入请求将得到有效处理,而不会产生酸洗,不会过多地传输large_obj
副本的内存(, 避免了任何形式的锁定和阻塞(但仍然可以进行性能扩展和延迟调整(,并根据需要将">计算"回复(大小合适、小而高效的答案(返回给相应的远程代理(。