Scipy.Optimize多进程优化如何实现迭代断点续存?
解决方案:多进程差分进化优化的迭代保存与恢复
你遇到的问题核心是多进程模式下,DifferentialEvolutionSolver内部的进程池(_pool)对象无法被pickle序列化——这是Python多进程模块的固有限制,进程池本身不能在进程间传递或持久化。要同时实现多进程加速和迭代保存,我们可以通过「序列化前清理进程池,恢复时重建进程池」的思路来解决。
具体实现步骤
- 保存求解器前,临时移除进程池
在调用pickle.dump()之前,将求解器的_pool属性设为None,避开无法序列化的进程池对象。 - 加载求解器后,重建进程池
从pickle文件加载求解器后,重新创建进程池,并修复求解器依赖的映射方法(_map)。
修改后的测试代码
import pickle from scipy.optimize._differentialevolution import DifferentialEvolutionSolver from multiprocessing import Pool def converter(x): # 替换为你的目标函数 return sum(x**2) bounds = [(-1, 1)] * 66 if __name__ == '__main__': # 初始化多进程模式的求解器 solver = DifferentialEvolutionSolver(converter, bounds, disp=True, seed=9, workers=-1, maxiter=1) # 迭代优化并逐次保存 for i in range(100): best_x, best_cost = next(solver) print(f"Iteration {i}: Minimum energy = {solver.population_energies.min()}") # 保存前移除进程池,避免pickle报错 solver._pool = None with open(f'solver_{i}.pkl', 'wb') as f: pickle.dump(solver, f) # --------------------------- # 加载并恢复优化的示例代码 # --------------------------- # 加载指定迭代进度的求解器 with open('solver_50.pkl', 'rb') as f: restored_solver = pickle.load(f) # 重建进程池并修复映射方法 restored_solver._pool = Pool(processes=restored_solver.workers) restored_solver._map = restored_solver._pool.map # 继续迭代优化 for i in range(50, 100): best_x, best_cost = next(restored_solver) print(f"Restored Iteration {i}: Minimum energy = {restored_solver.population_energies.min()}") # 再次保存前移除进程池 restored_solver._pool = None with open(f'solver_{i}.pkl', 'wb') as f: pickle.dump(restored_solver, f) # 程序结束时关闭进程池,避免资源泄漏 restored_solver._pool = Pool(processes=restored_solver.workers) restored_solver._pool.close() restored_solver._pool.join()
关键注意事项
- 进程池重建时机:必须在
if __name__ == '__main__':代码块内重建进程池,避免多进程环境下的重复初始化问题。 - 资源清理:在程序结束后,记得关闭并
join进程池,防止系统资源泄漏。 - 替代序列化工具:如果上述方法仍有问题,可以尝试用
dill库代替pickle(执行pip install dill安装),它支持更多Python对象的序列化,但进程池本身的限制依然存在,所以清理重建的步骤还是必要的。
内容的提问来源于stack exchange,提问作者Nicolas Vincent
相关产品推荐
相关产品推荐

