2016-11-09 5 views
4

Я пытаюсь параллельно моделировать несколько FMU Modelica, используя python/pyfmi и многопроцессорную обработку. Однако я не могу возвращать любые объекты FMI pyfmi из подпроцессов после инициализации FMU. Кажется, что объекты FMI pyfmi (например, pyfmi.fmi.FMUModelCS2 или pyfmi.fmi.FMUState2) не подбираются. Я также пробовал укротить рассол, который не работает для меня. С укропом объекты могут быть сорваны, но это означает отсутствие ошибки, но как-то испорчено, если я попытаюсь перезагрузить их потом. Кто-нибудь имеет представление о том, как решить эту проблему? Благодаря!Использование pyfmi с многопроцессорной обработкой для моделирования Modelica FMUs

+0

На самом деле мне уже удалось смоделировать параллельные FMU, используя функцию пула. Но я хочу сделать следующее: 1. Открытый пул процессов и карта с FMU 2. Инициализация и одновременное моделирование нескольких FMU параллельно только для одного временного сигнала 3. Возвращаемые результаты для дальнейшей обработки 4. Закрыть процессы 5. Откройте новый пул и повторите инициализацию с предыдущими состояниями FMU и входными значениями (которые не подбираются, как я понимаю) 6. Имитировать следующий timestep Возможно, это было не слишком ясно в моем предыдущем вопросе – Markus

ответ

2

Проблема заключается в том, что pyfmi.fmiFMUModelCS2 является классом Cython, зависящим от внешних библиотек, что делает его недоступным. Так что, к сожалению, это невозможно.

Если вы хотите использовать многопроцессорную обработку, единственный путь, который я вижу, это то, что вы сначала создаете процессы, а затем загружаете FMU в отдельные процессы. Таким образом, вам не нужно рассортировать классы.

+0

На самом деле мне уже удалось имитировать параллельные FMU, используя функцию пула. Но я хочу сделать следующее: 1. Открытый пул процессов и карта с FMU 2. Инициализация и одновременное моделирование нескольких FMU параллельно только за один временной интервал 3. Возвращаемые результаты для дальнейшей обработки 4. Закрыть процессы 5. Откройте новый пул и повторите инициализацию с предыдущими состояниями FMU (которые не подбираются, как я понимаю) – Markus

+0

Ок, я вижу. Состояние FMU не подбирается, поскольку в основном это указатель на внутреннюю структуру данных в FMU (в зависимости от инструмента, экспортирующего FMU).Лучше всего было бы взглянуть на методы FMI «fmi2SerializeFMUState» и т. Д. С их помощью у вас будет возможность сохранить состояние FMU в файл и прочитать его обратно. К сожалению, в настоящее время они не поддерживаются в PyFMI, но я не думаю, что это было бы большой частью усилий. –

+0

Спасибо большое! Я посмотрю на него и отчитаюсь. – Markus

3

У меня возникла аналогичная проблема, когда я создал 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

+0

@ Marco Bonvini Фрагменты кода в документации для примера довольно загадочны для меня. Может, там какая-то путаница? Я не понимаю, что одиночная фраза 'else' и' m' нигде не инициализируется. В противном случае, большое спасибо за указание на ваш отличный модуль! –

+1

Документы выбирают, какие строки включать в фрагмент. Строки должны были быть изменены с недавним фиксацией, а результат - вводящими в заблуждение фрагментами кода. Во всяком случае, лучше посмотреть исходный код примера https://github.com/lbl-srg/EstimationPy/blob/master/estimationpy/examples/first_order/run_pool.py –

0

Модуль 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) 

, которые я не в состоянии понять.