Трехслойная многопоточность с Pyomo - PullRequest
2 голосов
/ 09 июля 2019

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, и многослойная многопоточность перепутана.Итак, как правильно это сделать?

...