Использование pyfmi с многопроцессорной обработкой для моделирования FMU Modelica
Я пытаюсь смоделировать несколько FMU Modelica параллельно, используя python/pyfmi и многопроцессорность. Однако я не могу вернуть любые объекты Pymi-FMI из подпроцессов после инициализации FMU. Кажется, что объекты FMI pyfmi (например, pyfmi.fmi.FMUModelCS2 или pyfmi.fmi.FMUState2) недоступны для выбора. Я также попробовал мариновать укроп, который не работает для меня. С помощью укропа объекты могут быть отборными, то есть без ошибок, но как-то поврежденными, если я попытаюсь перезагрузить их потом. У кого-нибудь есть идеи, как решить эту проблему? Спасибо!
3 ответа
Проблема в том, что pyfmi.fmiFMUModelCS2 - это класс Cython, зависящий от внешних библиотек, что делает его недоступным для выбора. Так что, к сожалению, это невозможно.
Если вы хотите использовать многопроцессорность, я вижу только один способ - сначала создать процессы, а затем загрузить FMU в отдельные процессы. Таким образом, вам не нужно мариновать классы.
Я столкнулся с подобной проблемой, когда создал EsificationPy. В итоге я создал оболочку для параллельного моделирования одного и того же FMU с использованием нескольких процессов.
Я предлагаю вам посмотреть здесь реализацию https://github.com/lbl-srg/EstimationPy/blob/master/estimationpy/fmu_utils/fmu_pool.py
И к примеру http://lbl-srg.github.io/EstimationPy/modules/examples/first_order.html
Модуль pathos позволяет выполнять многопроцессорную обработку с интерфейсом, аналогичным multiprocessing
но полагается на укроп вместо pickle
для сериализации. Pool
метод работает для параллельного выполнения model.simulate
при условии, что результаты обрабатываются в памяти:
n_core = 2
n_simulation = 10
# ====
import pyfmi
model = pyfmi.load_fmu(path_fmu)
def worker(*args):
model.reset()
print "================> %d" % args[0]
return model.simulate(options=dict(result_handling="memory"))["y"]
from pathos.multiprocessing import Pool
pool = Pool(n_core)
out = pool.map(worker, range(n_simulation))
pool.close()
pool.join()
Обратите внимание, что в приведенном выше фрагменте необходимо обработать результаты в памяти: options=dict(result_handling="memory")
, По умолчанию используются временные файлы, которые работают, когда количество симуляций невелико. Однако чем длиннее очередь, тем выше шанс получить что-то вроде
Exception in thread Thread-27:
Traceback (most recent call last):
File "/home/USER/anaconda2/lib/python2.7/threading.py", line 801, in __bootstrap_inner
self.run()
File "/home/USER/anaconda2/lib/python2.7/threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "/home/USER/anaconda2/lib/python2.7/site-packages/multiprocess/pool.py", line 389, in _handle_results
task = get()
File "/home/USER/anaconda2/lib/python2.7/site-packages/dill/dill.py", line 260, in loads
return load(file)
File "/home/USER/anaconda2/lib/python2.7/site-packages/dill/dill.py", line 250, in load
obj = pik.load()
File "/home/USER/anaconda2/lib/python2.7/pickle.py", line 864, in load
dispatch[key](self)
File "/home/USER/anaconda2/lib/python2.7/pickle.py", line 1139, in load_reduce
value = func(*args)
TypeError: __init__() takes exactly 2 arguments (1 given)
что я не могу понять.