1

我正在使用 doopl.factory 在一个循环中解决多个线性程序。我注意到循环实例时性能下降。使用 memory_profiler 表明每次调用后内存都会增加,最终导致性能非常差。似乎doopl.factory.create_opl_model() 和opl.run() 以某种方式阻塞了未被opl.end() 清除的内存。我的分析正确吗?

memory_profiler 分析截图

我设置了一个简单的例子来演示这个问题。

import doopl.factory, os, psutil
from memory_profiler import profile


@profile
def main():

    dat = 'data.dat'
    mod = 'model.mod'

    print('memory before doopl: ' + str(psutil.Process(os.getpid()).memory_info().rss / 100000000) + ' GB')

    with doopl.factory.create_opl_model(model=mod, data=dat) as opl:
        try:
            opl.mute()
            opl.run()
            opl.end() **# EDIT:** this is just to explicitly demonstrate with memory_profiler that opl.end() does not free all memory.
        except:
            'error'

    print('memory after doopl: ' + str(psutil.Process(os.getpid()).memory_info().rss / 100000000) + ' GB')

if __name__ == "__main__":
    main()

data.dat 文件为空,model.mod 文件如下:

range X = 1..5;

dvar int+ y[X];

minimize sum(x in X) y[x];

subject to {
    forall (x in X) {
        y[x] <= 2;
    };
};

用doopl求解模型后有什么方法可以完全清除内存吗?

4

1 回答 1

0

你的代码怎么能工作?

opl.end() 将一些内部设置为无。如果你这样做:

with create_opl_model(model=mod) as opl:
   opl.run()
   opl.end()

opl.end() 实际上被调用了两次:一次是 opl.end() 然后一次是在上下文管理器退出时,导致异常。

如果您将 opl.end() 用作上下文管理器,请不要调用它。

除非您拥有非常旧的 doopl 版本(>2 年)。如果是这样,请升级..

现在,在 opl.end() 中,我可以告诉您 C++ 对象已正确释放。我不知道这里有任何内存泄漏问题(但 OPL 中的内存泄漏必须使用 c++ 来演示,而不是垃圾收集语言)。

据我所知,memory_profiler 是基于使用 psutil 的进程大小。不能保证当您释放一些内存时,进程大小会减小(python 可能已经释放了内存,但内存分配器可能没有将内存返回给系统)。

于 2021-03-11T08:42:23.983 回答