CPLEX Python API 性能开销?

5 投票
2 回答
1976 浏览
提问于 2025-04-17 18:26

更新

这个问题已经在OR exchange上进行了详细讨论和更新,我在那儿也发过这个问题。

原始问题

当我从命令行运行 CPLEX 12.5.0.0 时:

cplex -f my_instance.lp

找到一个最佳的整数解用了 19056.99 个时间单位。

但是通过 Python 接口,在同样的情况下:

import cplex
problem = cplex.Cplex("my_instance.lp")
problem.solve()

所需的时间变成了 97407.10 个时间单位(慢了超过 5 倍)。

在这两种情况下,模式都是并行的、确定性的,最多使用 2 个线程。我在想,这么慢的表现是不是因为 Python 线程的开销,于是我尝试了:

problem = cplex.Cplex("my_instance.lp")
problem.parameters.threads.set(1)
problem.solve()

结果是 46513.04 个时间单位(也就是说,使用一个核心的速度是使用两个核心的两倍!)。

作为 CPLEX 和线性规划的新手,我对这些结果感到很困惑。有没有办法提高 Python 接口的性能,或者我应该换用更成熟的接口(比如 Java 或 C++)呢?

附录

这里是 2 个线程的解决方案的详细信息,首先是(共同的)前言:

Tried aggregator 3 times.
MIP Presolve eliminated 2648 rows and 612 columns.
MIP Presolve modified 62 coefficients.
Aggregator did 13 substitutions.
Reduced MIP has 4229 rows, 1078 columns, and 13150 nonzeros.
Reduced MIP has 1071 binaries, 0 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.06 sec. (18.79 ticks)
Probing fixed 24 vars, tightened 0 bounds.
Probing time = 0.08 sec. (18.12 ticks)
Tried aggregator 1 time.
MIP Presolve eliminated 87 rows and 26 columns.
MIP Presolve modified 153 coefficients.
Reduced MIP has 4142 rows, 1052 columns, and 12916 nonzeros.
Reduced MIP has 1045 binaries, 7 generals, 0 SOSs, and 0 indicators.
Presolve time = 0.05 sec. (11.67 ticks)
Probing time = 0.01 sec. (1.06 ticks)
Clique table members: 4199.
MIP emphasis: balance optimality and feasibility.
MIP search method: dynamic search.
Parallel mode: deterministic, using up to 2 threads.
Root relaxation solution time = 0.20 sec. (91.45 ticks)

命令行的结果:

GUB cover cuts applied:  1
Clique cuts applied:  3
Cover cuts applied:  2
Implied bound cuts applied:  38
Zero-half cuts applied:  7
Gomory fractional cuts applied:  2

Root node processing (before b&c):
  Real time             =    5.27 sec. (2345.14 ticks)
Parallel b&c, 2 threads:
  Real time             =   35.15 sec. (16626.69 ticks)
  Sync time (average)   =    0.00 sec.
  Wait time (average)   =    0.00 sec.
                          ------------
Total (root+branch&cut) =   40.41 sec. (18971.82 ticks)

Python 接口的结果:

Clique cuts applied:  33
Cover cuts applied:  1
Implied bound cuts applied:  4
Zero-half cuts applied:  10
Gomory fractional cuts applied:  4

Root node processing (before b&c):
  Real time             =    6.42 sec. (2345.36 ticks)
Parallel b&c, 2 threads:
  Real time             =  222.28 sec. (95061.73 ticks)
  Sync time (average)   =    0.01 sec.
  Wait time (average)   =    0.00 sec.
                          ------------
Total (root+branch&cut) =  228.70 sec. (97407.10 ticks)

2 个回答

0

关于这个问题,我注意到在调用variables.add和linear_constraints.add之后,Python的API构建问题的时间明显变长。看起来是CPXLgetcolindex函数里的strcmp占用了大部分时间,可能是因为字符串ID在数组中是通过线性搜索来处理的吧?而在C++中,创建问题的速度是瞬间完成的。

1

你可以试着在这两种情况下都关闭预处理和剪切功能。然后重新进行实验,看看Python的接口是否在限制性能。如果关闭剪切后性能相同,那就要研究一下Python的剪切参数设置和默认值。

我个人觉得C++在性能方面更好,但使用它可能会让开发时间大大增加。这只是我的看法。

撰写回答