Python 2.7 利用pyfmi进行Modelica FMU的多处理仿真

Python 2.7 利用pyfmi进行Modelica FMU的多处理仿真,python-2.7,modelica,fmi,Python 2.7,Modelica,Fmi,我正在尝试使用python/pyfmi和多处理并行模拟多个Modelica FMU。但是,一旦FMU初始化,我无法从子流程返回任何pyfmi对象。pyfmi对象(例如pyfmi.FMI.FMUModelCS2或pyfmi.FMI.FMUState2)似乎不可拾取。我还试着用莳萝泡菜,但这对我来说并不管用。使用dill时,对象是可拾取的,这意味着没有错误,但如果我尝试在之后重新加载它们,它们会以某种方式损坏。有人知道如何解决这个问题吗?谢谢 问题在于pyfmi.fmiFMUModelCS2是一个依

我正在尝试使用python/pyfmi和多处理并行模拟多个Modelica FMU。但是,一旦FMU初始化,我无法从子流程返回任何pyfmi对象。pyfmi对象(例如pyfmi.FMI.FMUModelCS2或pyfmi.FMI.FMUState2)似乎不可拾取。我还试着用莳萝泡菜,但这对我来说并不管用。使用dill时,对象是可拾取的,这意味着没有错误,但如果我尝试在之后重新加载它们,它们会以某种方式损坏。有人知道如何解决这个问题吗?谢谢

问题在于pyfmi.fmiFMUModelCS2是一个依赖于外部库的Cython类,这使得它不可访问。不幸的是,这是不可能的


如果您想使用多处理,我看到的唯一前进方向是首先创建流程,然后将FMU加载到单独的流程中。这样,就不需要对类进行pickle处理。

在创建EstimationPy时,我遇到了类似的问题。我最终创建了一个包装器,用于使用多个进程运行同一FMU的并行模拟

我建议您看看这里的实现

对于示例

,模块允许使用与
多处理
类似的接口进行多处理,但依赖于而不是
pickle
进行序列化。
方法可用于并行执行
模型。模拟
,前提是结果在内存中处理:

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\u 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)

我无法理解。

事实上,我已经使用Pool函数模拟了并行FMU。但我想做的是:1。打开流程池并与FMU 2进行映射。仅在一个时间步3中,并行初始化和模拟多个FMU。返回要进一步处理的结果4。关闭进程5。打开新的池并用以前的FMU状态重新初始化(据我所知,这些状态是不可拾取的)Ok,我明白了。FMU状态不可拾取,因为它基本上只是指向FMU内部数据结构的指针(根据导出FMU的工具的不同而有所不同)。最好的办法是查看FMI方法“fmi2SerializeFMUState”等。使用这些方法,您可以选择将FMU状态存储到文件中并将其读回。不幸的是,PyFMI目前不支持它们,但我不相信将它们包括在内会有多大的努力。非常感谢!你好,克里斯蒂安,几周后我再次研究了所描述的问题,尝试了几种解决方法,但都没有成功。您提出的解决方案似乎是我最后的希望,我还研究了github上的fmi.pyx。问题是我对C代码和Cython不是很熟悉,实际上我完全不熟悉。你能就如何实现这些功能给我一些建议吗?有没有办法为pyfmi做出贡献?实际上,我已经设法使用Pool函数模拟了并行FMU。但我想做的是:1。打开流程池并与FMU 2进行映射。仅在一个时间步3中,并行初始化和模拟多个FMU。返回要进一步处理的结果4。关闭进程5。打开新的池,并使用以前的FMU状态和输入值(据我所知,它们是不可拾取的)重新初始化6。Simulate next timestep在我上面的问题@Marco Bonvini中可能不太清楚示例文档中的代码片段对我来说相当神秘。也许有点混乱?我不理解单独的
else
子句,而且
m
似乎没有在任何地方进行初始化。否则,非常感谢您指向您的优秀模块!文档正在选择要包含在代码段中的行。这些行必须随着最近的提交而更改,并且结果是误导性的代码片段。无论如何,最好直接查看示例的源代码