modelon-community / PyFMI

PyFMI is a package for loading and interacting with Functional Mock-Up Units (FMUs) both for Model Exchange and Co-Simulation, which are compiled dynamic models compliant with the Functional Mock-Up Interface (FMI)
http://jmodelica.org/pyfmi
GNU Lesser General Public License v3.0
164 stars 37 forks source link

Initializing models in parallel #28

Open missermann opened 4 years ago

missermann commented 4 years ago

Hi! I want to use pyfmi to simulate individual time steps (with do_step) in EnergyPlus. I recognized that initializing the individual EnergyPlus models takes quite some time. Therefore, I hope to find a way to initialize the models in parallel. If it matters, I am on Ubuntu 16.10 and use Python 3.6. Here is what I want to get done in serial:

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)

The result is a dictionary with ids as key and the models as value: {id1:FMUModelCS1,id2:FMUModelCS1}

I tried multiprocessing:

from   multiprocessing               import Process, Manager
from   pyfmi                         import load_fmu

def ep_intialization(bldg,lproxy):
    fmu         = {}
    final_time  = 60*60*24*7
    start_time  = 0
    chdir(fmu_path+str(bldg))
    fmu[bldg]   = load_fmu('f_' + str(bldg)+'.fmu',fmu_path+str(bldg))
    fmu[bldg].initialize(start_time,final_time)
    lproxy.append(fmu)

if __name__ == '__main__':
    manager = Manager()
    lproxy  = manager.list()
    jobs    = []
    for bldg in osmids_list:
        p   = Process(target=ep_intialization, args=(bldg,lproxy))
        jobs.append(p)
        p.start()
    for j in jobs:
        j.join()

This code sucessfully starts several processes on different cores (see in the system monitor), but when the fmus are dumped in the multiprocessing list, I get a pickling error. The multithreading with python's threading works, but the performance gains are marginal. I already tried different parallel processing/serialization approaches, such as dask, joblib, cloudpickle,pathos,dill, but to no avail.

I am aware that the FMUModels are cython classes, and thus really difficult to serialize. Pyfmi has pyfmi.master.Master which allows parallel simulation but not for FMUModelCS1 and with no do_step. There is an interesting point in the changelog:

— PyFMI-2.3 — Allow do steps to be performed in parallel (ticket:4541).

However, I couldnt find any other reference.

Any ideas on this issue?

trulede commented 4 years ago

If pickling is not working then I would leave the fmu object in the process, and then call it indirectly via another python object which you put into the lproxy list. That object might use a bit of python magic to simply proxy calls to the fmu instance in the process, rather than the fmu instance itself being the proxy.

trulede commented 4 years ago

This is what I had in mind: https://docs.python.org/3/library/multiprocessing.html#proxy-objects

piotre13 commented 1 year ago

@missermann Hi, I'm trying to do something similar to what you're doing. can I ask you, how many instances of the same FMU you are initializing and simulating? I'm trying to do that in co-simulation (that should ensure multiprocessing), but with more than 500 instances I get some errors from Eplus with the sockets, did you have a similar experience? Thanks

missermann commented 10 months ago

@piotre13 I only tried very few (under 10) since I never could get it working. How did you succeeded? Would you share your code?

piotre13 commented 10 months ago

@missermann I'm sorry the code is confidential and I would not be able to share it. But yes I'm running several (up to 500) fmu instances of energyplus model (really simple shoeboxes) using Mosaik cosimulation library and a custom-made mosaik API that call the dostep method using pyfmi. They are running and simulating but I still have some perplexities about some of the results that seem quite different when running the idf by itself. I've never tried to run several FMU instances without using the mosaik orchestrator so maybe the difference is this. If you have any doubts or suggestions it could be helpful to keep this thread on because it seems that on the web there are not many people trying to do this.