3.8.10. 高速化 TIPS

本項では,PySIMPLE の性能を引き出すことのできる高速化方法を 4 つ紹介します.

Set/Element の value には range を与える

Set の value キーワードには iterable オブジェクト全般を渡すことができますが, range の場合は専用の高速化処理が行われ,下記の例だと,10 倍程度の速度差が発生します. Element にも value キーワードがありますが同様です. 添字が等差数列の場合はなるべく range オブジェクトを渡すようにしましょう.:

I = Set(value=list(range(1000000)))  # 遅い
I = Set(value=range(1000000))        # 速い
set が同じ添字は使いまわす

Set や Element に value が与えられた場合は内部でデータチェックが行われます. 前者ではデータチェックが 2 回,後者では 1 回であるため,後者の方が速くなります.:

# 遅い
i1 = Element(value=range(1000000))
i2 = Element(value=range(1000000))
# 速い
I = Set(value=range(1000000))
i1 = Element(set=I)
i2 = Element(set=I)

後者は次のように記述することもできます.:

i1 = Element(value=range(1000000))
i2 = Element(set=i1.set)
制約より lb/ub を使う

PySIMPLE では変数の宣言時に lower/upper bound を与えることができます. bound に定数を渡した場合は,与えない場合と同じ速度で初期化が行われるため,後者では制約式の分,高速になります.:

i = Element(value=range(1000000))
p = Problem()
# 遅い
x = Variable(index=i)
p += x[i] >= 1
# 速い
x = Variable(index=i, lb=1)
データは宣言時に与える

PySIMPLE では Parameter の値や Variable の初期値を宣言時に与えることも,宣言後に変更することもできます. しかし,Parameter/Variable への代入は添字つき処理を行うことを目的として実装されているため, 通常の代入に比べると遅くなってしまいます. そのため,個別に値を指定したい場合は辞書を作成しておき,宣言時に与える方が効率的です.:

# 遅い
a = Parameter(index=i)
for idx in ...:
    a[idx] = ...

# 速い
data = {}
for idx in ...:
    data[idx] = ...
a = Parameter(index=i, value=data)

一方,次のような添字付き代入の場合は問題ありません.:

a = Parameter(index=i)
a[i] = i