我正在研究一个CPU密集型的ML问题,该问题的中心是一个加法模型。由于加法是主要的操作,所以我可以将输入数据分成几部分并生成多个模型,然后用覆盖的__add__
方法合并这些模型。在
与多处理相关的代码如下所示:
def pool_worker(filename, doshuffle):
print(f"Processing file: {filename}")
with open(filename, 'r') as f:
partial = FragmentModel(order=args.order, indata=f, shuffle=doshuffle)
return partial
def generateModel(is_mock=False, save=True):
model = None
with ThreadPool(args.nthreads) as pool:
from functools import partial
partial_models = pool.imap_unordered(partial(pool_worker, doshuffle=is_mock), args.input)
i = 0
for m in partial_models:
logger.info(f'Starting to merge model {i}')
if model is None:
import copy
model = copy.deepcopy(m)
else:
model += m
logger.info(f'Done merging...')
i += 1
return model
问题是,随着模型阶数的增加,内存消耗呈指数级增长,因此在4阶时,模型的每个实例大约为4-5gb,这会导致线程池崩溃,因为中间模型对象随后无法pickle。在
我读了一点这方面的文章,似乎即使酸洗不是问题,像这样传递数据仍然非常低效,正如对this answer所评论的那样。在
然而,对于如何使用共享内存来达到这个目的,几乎没有什么指导。有没有可能避免这个问题而不必改变模型对象的内部结构?在
从python3.8(alphanow)开始,将有^{} ,这将允许进程之间直接读/写数据共享,类似于其他语言(C、Java)中的“真正”多线程处理。在
与通过磁盘或套接字共享数据或其他需要序列化/反序列化和复制数据的通信相比,这将既快又容易使用。在
示例:
查看ray项目,它是一个分布式执行框架,它利用apache arrow进行序列化。如果您正在使用numpy数组,那么它将是一个非常好的ML工作流工具。在
以下是object serialization上的文档片段
在我看来,对于并行执行,它甚至比多处理库更容易使用,尤其是在希望使用共享内存时,这是tutorial中的用法介绍。在
使用文件!
不,真的,使用文件——它们是高效的(操作系统将缓存内容),并允许您处理更大的问题(数据集不必放入RAM)。在
使用https://docs.scipy.org/doc/numpy-1.15.0/reference/routines.io.html中的任意一个将numpy数组转储/加载到文件/从文件加载numpy数组,并且只在进程之间传递文件名。在
p.S.基准串行化方法,根据中间数组的大小,最快的可能是“原始”(无转换开销)或“压缩”(如果文件最终写入磁盘)或其他方法。IIRC加载“原始”文件可能需要事先知道数据格式(尺寸、大小)。在
相关问题 更多 >
编程相关推荐