减少 pyomo 模型的内存需求
Reducing memory requirements of a pyomo model
我正在构建一个包含超过 100 万个约束和 200 万个变量的大型 pyomo 模型。
我正在寻找减少我正在构建的模型的内存需求的建议。
目前它需要超过 20gb
的 RAM。
我该如何减少它?
我从未测试过定义变量 with/without within=pyomo.NonNegativeReals
。但我假设它会减少给定变量所需的内存量。在不减少变量或约束的数量的情况下,我还能做其他事情吗?
例如:
以下 var
将需要 X
字节的内存
m.var = pyomo.Var(
m.index)
也许下面需要 X-1
字节的内存
m.var = pyomo.Var(
m.index,
within=pyomo.NonNegativeReals)
当然这是一种推测。如果不进行测试,就无法确定这一点。但是,如果有人对此问题有想法或更多经验,我愿意尝试任何事情。
有什么想法吗?
一些测试:
请记住,这不是真实模型,而是使用其他数据构建的示例。但还是一样的脚本。
index=1000 // Full Consts // 347580 KB (commit) // 370652 KB (working set)
0 Const Full Rules // 282416 KB (commit) // 305252 KB (working set)
0 Const 0 Rule // 282404 KB (commit) // 305200 KB (working set)
1 Const 1 Rule // 290408 KB (commit) // 313136 KB (working set)
index=8760 // Full Consts // 1675860 KB (commit) // 1695676 KB (working set)
我已经使用 pympler
分析了您向我指出的测试用例。这是我发现的:
在 pyomo_model_prep
之后(加载数据并将其放入空 ConcreteModel
):
- 内存使用量为 13.2 MB
添加所有 Set
和 Param
对象后:
- 内存使用量为 13.3 MB
添加所有 Var
个对象后:
- 内存使用量为 14.3 MB
添加所有 Constraint
个对象后:
- 内存使用量为 15.0 MB
当我将时间步设置为 60 时,结果是
- 内存使用量为 13.2 MB(数据)
- 内存使用量为 13.3 MB(设置、参数后)
- 内存使用量为 19.6 MB(在 vars 之后)
- 内存使用量为 23.6 MB(约束后)
所以当时间步数较多时,变量确实对模型内存有很大影响。我能看到的减少内存使用的唯一明显的地方是不要将所有数据存储在模型上(或者在不再需要后从模型中删除它),然后垃圾收集器可能会清理未使用的数据.
不幸的是,实际上并没有任何简单的方法来减少变量声明的内存。
更新 1:仅供参考,变量声明的几乎所有内存使用都是 e_pro_in
和 e_pro_out
索引变量的结果。
更新2:如果模型中没有使用e_pro_in
和e_pro_out
变量的大量索引,您可以通过为每个变量构建一个简化的索引集来减少内存需求.这是它的样子:
e_pro_in_index = []
for t in m.tm:
for i,j in m.pro_tuples:
for c in m.com:
if ...:
e_pro_in_index.append((t,i,j,c))
m.e_pro_in_index = Set(dimen=4, initialize=e_pro_in_index)
m.e_pro_in = pyomo.Var(
m.e_pro_in_index,
within=pyomo.NonNegativeReals,
doc='Power flow of commodity into process (MW) per timestep')
您需要从约束规则中提取逻辑以找出不需要的索引。
我正在构建一个包含超过 100 万个约束和 200 万个变量的大型 pyomo 模型。
我正在寻找减少我正在构建的模型的内存需求的建议。
目前它需要超过 20gb
的 RAM。
我该如何减少它?
我从未测试过定义变量 with/without within=pyomo.NonNegativeReals
。但我假设它会减少给定变量所需的内存量。在不减少变量或约束的数量的情况下,我还能做其他事情吗?
例如:
以下 var
将需要 X
字节的内存
m.var = pyomo.Var(
m.index)
也许下面需要 X-1
字节的内存
m.var = pyomo.Var(
m.index,
within=pyomo.NonNegativeReals)
当然这是一种推测。如果不进行测试,就无法确定这一点。但是,如果有人对此问题有想法或更多经验,我愿意尝试任何事情。
有什么想法吗?
一些测试:
请记住,这不是真实模型,而是使用其他数据构建的示例。但还是一样的脚本。
index=1000 // Full Consts // 347580 KB (commit) // 370652 KB (working set)
0 Const Full Rules // 282416 KB (commit) // 305252 KB (working set)
0 Const 0 Rule // 282404 KB (commit) // 305200 KB (working set)
1 Const 1 Rule // 290408 KB (commit) // 313136 KB (working set)
index=8760 // Full Consts // 1675860 KB (commit) // 1695676 KB (working set)
我已经使用 pympler
分析了您向我指出的测试用例。这是我发现的:
在 pyomo_model_prep
之后(加载数据并将其放入空 ConcreteModel
):
- 内存使用量为 13.2 MB
添加所有 Set
和 Param
对象后:
- 内存使用量为 13.3 MB
添加所有 Var
个对象后:
- 内存使用量为 14.3 MB
添加所有 Constraint
个对象后:
- 内存使用量为 15.0 MB
当我将时间步设置为 60 时,结果是
- 内存使用量为 13.2 MB(数据)
- 内存使用量为 13.3 MB(设置、参数后)
- 内存使用量为 19.6 MB(在 vars 之后)
- 内存使用量为 23.6 MB(约束后)
所以当时间步数较多时,变量确实对模型内存有很大影响。我能看到的减少内存使用的唯一明显的地方是不要将所有数据存储在模型上(或者在不再需要后从模型中删除它),然后垃圾收集器可能会清理未使用的数据.
不幸的是,实际上并没有任何简单的方法来减少变量声明的内存。
更新 1:仅供参考,变量声明的几乎所有内存使用都是 e_pro_in
和 e_pro_out
索引变量的结果。
更新2:如果模型中没有使用e_pro_in
和e_pro_out
变量的大量索引,您可以通过为每个变量构建一个简化的索引集来减少内存需求.这是它的样子:
e_pro_in_index = []
for t in m.tm:
for i,j in m.pro_tuples:
for c in m.com:
if ...:
e_pro_in_index.append((t,i,j,c))
m.e_pro_in_index = Set(dimen=4, initialize=e_pro_in_index)
m.e_pro_in = pyomo.Var(
m.e_pro_in_index,
within=pyomo.NonNegativeReals,
doc='Power flow of commodity into process (MW) per timestep')
您需要从约束规则中提取逻辑以找出不需要的索引。