pyomo 写模型似乎很慢

Posted

技术标签:

【中文标题】pyomo 写模型似乎很慢【英文标题】:pyomo seems very slow to write models 【发布时间】:2018-12-18 13:01:38 【问题描述】:

我有一个相当大的模型(大约 500 万个变量和约束)。

构建时间是几分钟,求解时间也是几分钟(使用 gurobi)

但是写模型需要很长时间(大约2小时)

如果我使用model.write('model.lp', io_options='symbolic_solver_labels': True) 可以记录它,这是时候

如果我直接使用pyomo的模型SolverFactorysolve,时间差不多

这里有一个小样本,我知道这个模型对于 gurobi 来说是微不足道的,所以我没有在这里比较求解时间和构建时间,但我不明白为什么它这么长,我认为问题可能来自磁盘写入速度,但似乎磁盘从不超载,几乎没有使用

import pyomo.environ as pyo
import time

size = 500000

model = pyo.ConcreteModel()
model.set = pyo.RangeSet(0, size)
model.x = pyo.Var(model.set, within=pyo.Reals)
model.constrList = pyo.ConstraintList()
for i in range(size):
    model.constrList.add(expr = model.x[i] >= 1)
model.obj = pyo.Objective(expr=sum(model.x[i] for i in range(size)), sense=pyo.minimize)

opt = pyo.SolverFactory('gurobi')

_time = time.time()
res = opt.solve(model)
print(">>> total time () in :.2fs".format(time.time() - _time))

print(res)

结果是整个求解函数的时间为27 s,而gurobi的求解时间仅为4 s。

【问题讨论】:

【参考方案1】:

检查您是否安装了最新版本的 pyomo 也是值得的。我最近从 v 5.5.0 更新到 5.6.8,发现构建 + 解决时间从 5 秒减少到 1 秒(对于一个明显比你的问题小得多的问题!)。

【讨论】:

【参考方案2】:

从我加快 pyomo 模型生成的轨迹来看,您需要首先对进程的哪个部分减慢它进行基准测试。 (这确实是性能调优的一般建议)

所以我把你的代码放到一个函数中:

def main():
    size = 500000

    model = pyo.ConcreteModel()
    model.set = pyo.RangeSet(0, size)
    model.x = pyo.Var(model.set, within=pyo.Reals)
    model.constrList = pyo.ConstraintList()
    for i in range(size):
        model.constrList.add(expr = model.x[i] >= 1)
    model.obj = pyo.Objective(expr=sum(model.x[i] for i in range(size)), sense=pyo.minimize)
    return model

所以我可以通过 ipython 中的 line profiler 运行:

In [1]: %load_ext line_profiler                                                                                                                                                                         

In [2]: import test_pyo                                                                                                                                                                                 

In [3]: %lprun -f test_pyo.main test_pyo.main()

这说明大部分时间都花在了model.constrList.add(expr = model.x[i] >= 1)上。

将其移入基于规则的约束中并没有看到太大的改进,因此我决定尝试手动构建表达式,就像在PyPSA code 中一样。

import pyomo.environ as pyo
import time
from pyomo.core.expr.numeric_expr import LinearExpression
from pyomo.core.base.constraint import _GeneralConstraintData
from pyomo.core.base.numvalue import NumericConstant

def main():
    size = 500000

    model = pyo.ConcreteModel()
    model.set = pyo.RangeSet(0, size)
    model.x = pyo.Var(model.set, within=pyo.Reals)
    setattr(model, "constraint", pyo.Constraint(model.set, noruleinit=True))
    v = getattr(model, "constraint")
    for i in v._index:
        v._data[i] = _GeneralConstraintData(None, v)
        expr = LinearExpression()
        expr.linear_vars = [model.x[i]]
        expr.linear_coefs = [1]
        expr.constant = 0
        v._data[i]._body = expr
        v._data[i]._equality = False
        v._data[i]._lower = NumericConstant(1)
        v._data[i]._upper = None

    model.obj = pyo.Objective(expr=pyo.quicksum(model.x[i] for i in range(size)), sense=pyo.minimize)
    return model

这似乎产生了大约 50% 的性能提升。线分析器显示,现在花费大量时间来创建集合、空 LinearExpression 对象以及创建目标。调整目标可能会使事情变得更好。

【讨论】:

事实证明,如果您还手动为目标创建 LinearExpression,您可以获得另一个小的改进【参考方案3】:

我认为你的隐含问题是“我怎样才能让它更快?”

如果写入时间有问题,您可以查看 Gurobi SolverFactory('gurobi', io_format='python') 的直接 python 接口。将symbolic_solver_labels 标志设置为True 几乎总是会增加模型的写入时间,因为组件名称查找可能很昂贵。

【讨论】:

感谢您的回答,io_format='python' 似乎对速度影响不大,对于符号标签,我通常只为调试编写模型,所以我需要标签 啊,所以您的首要任务是能够写出整个模型以进行调试?或者您只是想检查模型的某个部分? 编写模型时我并不关心速度,因为我只是在调试时使用它。直接从 pyomo 解决时,我的问题更多,我期望模型的构建时间在求解时间旁边可以忽略不计,但反过来,这就是我不明白的地方

以上是关于pyomo 写模型似乎很慢的主要内容,如果未能解决你的问题,请参考以下文章

win10电脑打开此电脑资源管理器任务管理器软件等突然很慢很慢,cup内存磁盘利用率却很低

SAP migo这个事物代码在做操作的时候,多人操作同一个事务代码时很慢很慢,是啥原因?

jsp做的网页,用tomcat测试时读数据库数据时很慢很慢,是啥原因?

公司网络很慢很卡的原因分析与处理

数据结构

mac 电脑启动项目很慢,本地服务调用很慢的解决办法!!