Performance differences in creation of MLinExpr and constraint addition in Python API
回答済みHello, I have recently noticed performance differences in the creation of MLinExprs and the addition of constraints from MLinExpr.
import timeit
import numpy as np
setup="""
import gurobipy as gb
model = gb.Model()
x = model.addMVar(shape=(100,100), name='x')
y = model.addMVar(shape=(100,100), name='y')"""
stmt1 = "x-y"
stmt2 = "x.reshape(-1) - y.reshape(-1)"
res1 = np.min(timeit.repeat(stmt=stmt1,setup=setup,repeat=1000,number=1))
res2 = np.min(timeit.repeat(stmt=stmt2,setup=setup,repeat=1000,number=1))
print(f'RES 1: {res1:.5f}')
print(f'RES 2: {res2:.5f}')
print(f'RES1 / RES2: {res1/res2:.5f}')RES 1: 0.01304
RES 2: 0.00095
RES1 / RES2: 13.78600Creating an MLinExpr from the reshaped MVars results in a ~14x speed up on my machine
import timeit
import numpy as np
setup1="""
import gurobipy as gb
model = gb.Model()
x = model.addMVar(shape=(100,100), name='x')
y = model.addMVar(shape=(100,100), name='y')
lhs = x-y
"""
setup2="""
import gurobipy as gb
model = gb.Model()
x = model.addMVar(shape=(100,100), name='x')
y = model.addMVar(shape=(100,100), name='y')
lhs = x.reshape(-1) - y.reshape(-1)
"""
stmt = "model.addConstr(lhs==0)"
res1 = np.min(timeit.repeat(stmt=stmt,setup=setup1,repeat=1000,number=1))
res2 = np.min(timeit.repeat(stmt=stmt,setup=setup2,repeat=1000,number=1))
print(f'RES 1: {res1}')
print(f'RES 2: {res2}')
print(f'RES1 / RES2: {res1/res2}')
RES 1: 0.02762570000049891
RES 2: 0.006292300000495743
RES1 / RES2: 4.390397787505745The addition of constraints from the different shaped MLinExprs results in a ~4x speed up on my machine.
If I understand correctly, the constraints added to the model are equivalent. The only difference is that the returned MConstr object now has a shape of 10,000x1 vs 100x100.
I'm just curious why is this the case? Is there any drawback to reshaping the MVars into vectors for constraint addition? Am I simply missing something obvious?
Thanks in advance,
Dillon
-
Hi Dillon,
Under the hood the matrix API leverages NumPy and SciPy.
We explicitly check if operands are 1 dimensional because there are some methods from these libraries that we can use to construct the results faster.
No drawback to reshaping comes to mind, but I'll ask the developers if they have any thoughts.
- Riley
0
サインインしてコメントを残してください。
コメント
1件のコメント