Pyomo需要解决三层多线程框架底层的优化问题。为了更好地说明这一点,下面显示了一个简化的示例:TopProblem是主线程,它创建了三个MiddleProblem线程;然后,每个MiddleProblem线程都会创建三个BottomProblem线程来解决Pyomo问题。
import threading
from pyomo.environ import *
import pyutilib.subprocess.GlobalData
pyutilib.subprocess.GlobalData.DEFINE_SIGNAL_HANDLERS_DEFAULT = False # This enables multi-thread for pyomo
class BottomProblem(threading.Thread):
def __init__(self, i, j):
threading.Thread.__init__(self)
self.i = i
self.j = j
def run(self):
model = ConcreteModel()
model.x = Var([1, 2])
model.obj = Objective(expr=model.x[1] ** 2 + model.x[2] ** 2)
model.constraint = Constraint(expr=(self.i + 1) * model.x[1] + (self.j + 1) * model.x[2] == 2)
opt = SolverFactory('ipopt')
opt.solve(model)
print('Solved problem (%d, %d)!' % (self.i, self.j))
class MiddleProblem(threading.Thread):
def __init__(self, i):
threading.Thread.__init__(self)
self.i = i
def run(self):
threads = [None, None, None]
for idx in range(3):
threads[idx] = BottomProblem(self.i, idx)
threads[idx].start()
for idx in range(3):
threads[idx].join()
class TopProblem(object):
def run(self):
top_threads = [None, None, None]
for idx in range(3):
top_threads[idx] = MiddleProblem(idx)
top_threads[idx].start()
for idx in range(3):
top_threads[idx].join()
top = TopProblem()
top.run()
这是简化版本,所有其他无关的细节均被省略。 (在MiddleProblem层中还需要执行其他一些任务,因此我有必要创建一个三层的多线程框架。)
运行此代码时,发生求解器错误:
ERROR: Solver (ipopt) returned non-zero return code (1)
ERROR: Solver log: Ipopt 3.12.12: /anaconda3/envs/pyomo/bin/ipopt: can't open
/var/folders/r7/1rbnyqbn1pv0dhb787m40qk50w71fq/T/tmpqtaxc2li.pyomo.nl
Exception in thread Thread-10:
Traceback (most recent call last):
File "/anaconda3/envs/pyomo/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "multithread_pyomo_test.py", line 29, in run
opt.solve(model)
File "/anaconda3/envs/pyomo/lib/python3.7/site-packages/pyomo/opt/base/solvers.py", line 600, in solve
"Solver (%s) did not exit normally" % self.name)
pyutilib.common._exceptions.ApplicationError: Solver (ipopt) did not exit normally
此错误的发生是随机的:有时无错误;有时会出现一些线程错误。
在我看来Pyomo和三层多线程搞砸了。那么正确的方法是什么?