使用joblib多进程时dill序列化耗时剧增问题求助
问题原因及解决方案
核心原因
- GIL(全局解释器锁)限制:你使用的是
threading后端,而Python的GIL会让CPU密集型任务(比如dill序列化)在多线程环境下实际串行执行。10个线程排队处理,每个线程都要等待前面的任务完成,总耗时被拉长至10倍,单个线程的耗时自然也变成了10分钟。 - 文件写入竞争:所有线程都在写入同一个
temp.zip文件,操作系统的文件锁机制会让线程等待文件释放,进一步加剧耗时。 - dill序列化的线程安全性:dill内部的部分操作可能并非线程安全,多线程并发调用时会触发额外的锁等待,增加序列化时间。
解决办法
- 切换到多进程后端:joblib默认的
loky后端(或multiprocessing)支持真正的多进程并行,每个进程拥有独立的GIL,能充分利用多核CPU。修改代码如下:
也可显式指定:if __name__ == '__main__': # 移除threading后端,默认使用loky out = Parallel(n_jobs=-1)(delayed(experiment)(obj) for obj in objs)with parallel_backend('loky', n_jobs=-1): out = Parallel()(delayed(experiment)(obj) for obj in objs) - 避免文件冲突:为每个任务分配独立的文件名,比如根据实例索引生成:
def experiment(obj, idx): zip_file= f"temp_{idx}.zip" with ZipFile(zip_file, 'w') as f: pickle.dump(obj, f, protocol=pickle.DEFAULT_PROTOCOL) if __name__ == '__main__': out = Parallel(n_jobs=-1)(delayed(experiment)(obj, i) for i, obj in enumerate(objs)) - 优化序列化效率:如果dill序列化仍然较慢,可尝试:
- 使用更高的pickle协议版本(比如
protocol=pickle.HIGHEST_PROTOCOL) - 检查
obj结构,移除不必要的可序列化对象,减少序列化体积
- 使用更高的pickle协议版本(比如
内容的提问来源于stack exchange,提问作者Hami
相关产品推荐
相关产品推荐

