Я пытаюсь параллельно моделировать несколько FMU Modelica, используя python/pyfmi и многопроцессорную обработку. Однако я не могу возвращать любые объекты FMI pyfmi из подпроцессов после инициализации FMU. Кажется, что объекты FMI pyfmi (например, pyfmi.fmi.FMUModelCS2 или pyfmi.fmi.FMUState2) не подбираются. Я также пробовал укротить рассол, который не работает для меня. С укропом объекты могут быть сорваны, но это означает отсутствие ошибки, но как-то испорчено, если я попытаюсь перезагрузить их потом. Кто-нибудь имеет представление о том, как решить эту проблему? Благодаря!Использование pyfmi с многопроцессорной обработкой для моделирования Modelica FMUs
ответ
Проблема заключается в том, что pyfmi.fmiFMUModelCS2 является классом Cython, зависящим от внешних библиотек, что делает его недоступным. Так что, к сожалению, это невозможно.
Если вы хотите использовать многопроцессорную обработку, единственный путь, который я вижу, это то, что вы сначала создаете процессы, а затем загружаете FMU в отдельные процессы. Таким образом, вам не нужно рассортировать классы.
На самом деле мне уже удалось имитировать параллельные FMU, используя функцию пула. Но я хочу сделать следующее: 1. Открытый пул процессов и карта с FMU 2. Инициализация и одновременное моделирование нескольких FMU параллельно только за один временной интервал 3. Возвращаемые результаты для дальнейшей обработки 4. Закрыть процессы 5. Откройте новый пул и повторите инициализацию с предыдущими состояниями FMU (которые не подбираются, как я понимаю) – Markus
Ок, я вижу. Состояние FMU не подбирается, поскольку в основном это указатель на внутреннюю структуру данных в FMU (в зависимости от инструмента, экспортирующего FMU).Лучше всего было бы взглянуть на методы FMI «fmi2SerializeFMUState» и т. Д. С их помощью у вас будет возможность сохранить состояние FMU в файл и прочитать его обратно. К сожалению, в настоящее время они не поддерживаются в PyFMI, но я не думаю, что это было бы большой частью усилий. –
Спасибо большое! Я посмотрю на него и отчитаюсь. – Markus
У меня возникла аналогичная проблема, когда я создал EstimationPy. Я закончил создание обертки для параллельного моделирования того же 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#run-multiple-simulations
@ Marco Bonvini Фрагменты кода в документации для примера довольно загадочны для меня. Может, там какая-то путаница? Я не понимаю, что одиночная фраза 'else' и' m' нигде не инициализируется. В противном случае, большое спасибо за указание на ваш отличный модуль! –
Документы выбирают, какие строки включать в фрагмент. Строки должны были быть изменены с недавним фиксацией, а результат - вводящими в заблуждение фрагментами кода. Во всяком случае, лучше посмотреть исходный код примера https://github.com/lbl-srg/EstimationPy/blob/master/estimationpy/examples/first_order/run_pool.py –
Модуль pathos позволяет мультипроцессирование с подобным интерфейсом как multiprocessing
, но полагается на dill вместо 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)
, которые я не в состоянии понять.
На самом деле мне уже удалось смоделировать параллельные FMU, используя функцию пула. Но я хочу сделать следующее: 1. Открытый пул процессов и карта с FMU 2. Инициализация и одновременное моделирование нескольких FMU параллельно только для одного временного сигнала 3. Возвращаемые результаты для дальнейшей обработки 4. Закрыть процессы 5. Откройте новый пул и повторите инициализацию с предыдущими состояниями FMU и входными значениями (которые не подбираются, как я понимаю) 6. Имитировать следующий timestep Возможно, это было не слишком ясно в моем предыдущем вопросе – Markus