forの高速化
Pythonの話じゃなくてPyPyの話かもしれない
2次元配列
2次元配列A[i][j]について2重のforで処理するとき、
forの順番が交換可能なら、添字の順番を外→内にすると速い
forが交換不可能なら、forに併せて合わせて添字が外→内になるように配列を定義したい
後からまとめてindexをつけて参照するよりも、forの直後に配列の参照を変数にブチ込んだほうが速い
例:行列の積 $ C = AB
遅い
code:matrix_mul_slow.py
for i in range(N):
for j in range(N):
for k in range(N):
$ N = 1000、PyPy3.10で9450ms
若干速い
code:matrix_mul_slow.py
for i in range(N):
for k in range(N):
for j in range(N):
$ N = 1000、PyPy3.10で6610ms
速い
code:matrix_mul_fast.py
for i in range(N):
Ci, Ai = Ci, Ai # 配列の参照を変数に収めておく for k in range(N):
for j in range(N):
$ N = 1000、PyPy3で1820ms。約5倍速い
内側の配列の大きさが大きくなるように設計しても速いらしい
numpy や numba で高速化させる方法もあるらしい
多重for
配列から何個か取り出す組み合わせ全探索を多重forで作る時、添字小さい方から決める感じにした方が速い
速い
code:combination_fast.py
for i1 in range(N):
for i2 in range(i1+1, N):
for i3 in range(i2+1, N):
for i4 in range(i3+1, N):
for i5 in range(i4+1, N):
hogehoge()
$ N = 150、PyPy3で1010ms
遅い
code:combination_slow.py
for i1 in range(N):
for i2 in range(i1):
for i3 in range(i2):
for i4 in range(i3):
for i5 in range(i4):
hogehoge()
$ N = 150、PyPy3で5094ms
ちなみにitertools.combinationsはもっと遅いらしい
code:combination_itertools.py
from itertools import combinations
for b in combinations(range(N), 5):
hogehoge()
$ N = 150、PyPy3でTLE (>10000ms)
Pythonだと速度差はあまりない