Python multiprocessing与Gurobi兼容问题:__getstate__ KeyError报错
Gurobi模型与Python多进程的序列化兼容问题解决
这个问题我之前也碰到过,本质是Python多进程的序列化机制和Gurobi底层C++对象的冲突导致的。先理清楚你的场景:
- 不含Gurobi
Model的类用multiprocessing.Pool跑多进程完全正常 - 一旦在类的
__init__里初始化Gurobi模型,调用pool.map就会抛出KeyError: '__getstate__' - 串行执行的版本却没有任何问题
报错原因
Python的multiprocessing模块在创建子进程时,会把父进程中需要传递的对象用pickle序列化,然后在子进程中反序列化还原。但Gurobi的Model对象:
- 是底层C++实现的复杂对象,没有实现Python pickle机制要求的
__getstate__和__setstate__方法 - 当你把包含
self.b = Model()的类实例传递给子进程时,pickle无法处理这个非纯Python对象,直接触发了KeyError
可行的解决方法
根据你的实际需求,这里有几个实用的方案:
方案1:延迟初始化Gurobi模型(最推荐)
不在类的构造函数里创建Model,而是在子进程执行的函数内部按需初始化。这样每个子进程会独立创建自己的Model实例,完全避开序列化问题:
from multiprocessing import Pool from gurobipy import * class A(object): def __init__(self): # 初始化时不创建Model self.b = None def square(self, x): # 子进程执行时才初始化Model(如果业务需要用到的话) if self.b is None: self.b = Model() return x * x def test(self): pool = Pool() result = pool.map(self.square, range(5)) return result A().test()
方案2:抽离并行逻辑为独立函数
把需要并行执行的代码从类实例中抽出来,改成独立的函数,这样就不需要序列化整个包含Model的类对象了:
from multiprocessing import Pool from gurobipy import * # 独立的并行函数,按需创建Model def square(x): b = Model() return x * x class A(object): def __init__(self): self.b = Model() def test(self): pool = Pool() result = pool.map(square, range(5)) return result A().test()
方案3:使用进程管理器托管模型(不推荐,仅特殊场景用)
如果确实需要在进程间共享Gurobi模型(注意:Gurobi官方不推荐多进程共享同一个Model,容易出现并发问题),可以用multiprocessing.Manager来托管模型对象:
from multiprocessing import Pool, Manager from gurobipy import * class A(object): def __init__(self, manager): # 通过Manager创建并托管Model对象 self.b = manager.Value(Model, Model()) def square(self, x): return x * x def test(self): pool = Pool() result = pool.map(self.square, range(5)) return result if __name__ == "__main__": with Manager() as manager: A(manager).test()
内容的提问来源于stack exchange,提问作者J. Lin
相关产品推荐
相关产品推荐

