Использование 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)

что я не могу понять.

Другие вопросы по тегам