Как инициализировать модели PYFMI параллельно? - PullRequest
0 голосов
/ 03 февраля 2020

Я использую pyfmi для симуляции с EnergyPlus. Я понял, что инициализация отдельных моделей EnergyPlus занимает довольно много времени. Поэтому я надеюсь найти способ инициализации моделей параллельно. Я попробовал многопроцессорную работу библиотеки python безуспешно. Если это имеет значение, я нахожусь на Ubuntu 16.10 и использую Python 3.6. Вот что я хочу сделать в сериале:

fmus        = {}
for id in id_list:
    chdir(fmu_path+str(id))
    fmus[id]  = load_fmu('f_' + str(id)+'.fmu',fmu_path+str(id))
    fmus[id].initialize(start_time,final_time)

В результате получается словарь с идентификаторами в качестве ключа и моделями в качестве значения: {id1:FMUModelCS1,id2:FMUModelCS1}

Цель - позвонить позже. модели по ключу и выполняют моделирование.

Вот моя попытка многопроцессорной обработки:

def ep_intialization(id,start_time,final_time):
    chdir(fmu_path+str(id))
    model  = load_fmu('f_' + str(id)+'.fmu',fmu_path+str(id))
    model.initialize(start_time,final_time)
    return {id:model}

data         = ((id,start_time,final_time) for id in id_list)
if __name__ == '__main__':
    pool         = Pool(processes=cpus)
    pool.starmap(ep_intialization, data)
    pool.close() 
    pool.join() 

Я вижу процессы моделей в моем системном мониторе, но затем скрипт вызывает ошибку потому что модели нельзя выбирать:

MaybeEncodingError: Error sending result: '[{id2: <pyfmi.fmi.FMUModelCS1 object at 0x561eaf851188>}]'. Reason: 'TypeError('self._fmu,self.callBackFunctions,self.callbacks,self.context,self.variable_list cannot be converted to a Python object for pickling',)'

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

Я видел этот ответ , но похоже, что он фокусируется на симуляции после инициализации.

1 Ответ

1 голос
/ 03 февраля 2020

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

Я пытался с пафосом , предложенным в этот ответ , но столкнуться с той же проблемой:

from pyfmi import load_fmu
from multiprocessing import Pool
from os import chdir
from pathos.multiprocessing import Pool

def ep_intialization(id):
    chdir('folder' + str(id))
    model  = load_fmu('BouncingBall.fmu')
    model.initialize(0,10)
    return {id:model}

id_list = [1,2]
cpus = 2    
data = ((id) for id in id_list)

pool = Pool(cpus)
out = pool.map(ep_intialization, data)

Это дает:

MaybeEncodingError: Error sending result: '[{1: <pyfmi.fmi.FMUModelME2 object at 0x564e0c529290>}]'. Reason: 'TypeError('self._context,self._fmu,self.callBackFunctions,self.callbacks cannot be converted to a Python object for pickling',)'

Вот еще одна идея:

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

Это было бы намного эффективнее: вы нужно было бы только создать экземпляр одного FMU и вызвать его параллельно с другими параметрами и входами.

Пример:

Я никогда не работал с EnergyPlus, но, возможно, следующий пример проиллюстрирует подход :

У вас есть три варианта здания, и вы просто заинтересованы в общем тепловом потоке по всей площади зданий в зависимости от «погоды» (что бы это ни значило - возможно, много переменных) .

Объедините все три здания в одну модель EnergyPlus и создайте вокруг них if или case (псевдокод):

if (id_building == 1) {
    [model the building one]
elseif (if_building == 2) {
    [model the building two]
[...]

Определите «погоду» или что вам нужно в качестве входной переменной для FMU и определите id_building также как параметр . Определите общий тепловой поток в качестве выходной переменной.

Это позволит вам выбрать здание до начала моделирования.

Два требования:

  1. Синтаксис EnergyPlus позволяет , если или case структуры.
  2. Все ваши модели работают с одним и тем же интерфейсом (в нашем примере у нас есть переменная погоды как in и переменная как out)

Существует грязный обходной путь для второго требования: просто определите все переменные, которые нужны всем вашим моделям, и используйте только то, что вам нужно в соответствующем блоке if.

...