はじめに
Σ計算がfor文のようなものであることはご存じだと思いますが、ただでさえPythonは遅いので素直にfor文でまわしていたら大きなデータの時に多くの時間を要してしまいます。参考書によるとfor文よりも内積使った方が速いらしいです。要素の合計といえばNumpyのsum関数があるので、それも含めた3種類で比較してみました。具体的な内積の考え方は後述します。自分の予想としてはsum関数がなんだかんだ一番速いと思います。根拠はないです。
プログラム
#for文
import numpy as np
import time
for i in range(10):
a = 0
c = np.linspace(2,10000000,5000000)
t1 = time.time()
for j in c:
a = a + int(j)
print(a)
t2 = time.time()
t = t2 - t1
print(t)
#sum関数
import numpy as np
import time
for i in range(10):
c = np.linspace(2,10000000,5000000)
t1 = time.time()
print(sum(c))
t2 = time.time()
t = t2 - t1
print(t)
#内積
import numpy as np
import time
for i in range(10):
c = np.linspace(2,10000000,5000000)
t1 = time.time()
d = np.ones(5000000)
print(np.dot(c,d))
t2 = time.time()
t = t2 - t1
print(t)
今回扱った配列はlinspaceで用意しています。2から10000000を5000000等分した等差数列となっています。time関数がたまーに機能しなくなるので逐一出力させています。ついでに合計も。for文のプログラムは配列の要素を1つ1つ読み込んで足しています。sum関数は引数に配列ぶっこむだけです。そして問題の内積さん。Numpy配列はベクトルであるため要素が全て1のベクトルを用意し、合計を求めたい配列(ベクトル)との内積をとるだけです。ベクトルの内積は各要素の積を足したスカラー量であるのでこの場合のベクトルの内積は配列の合計と等しいことがわかります。np.dot(a,b)でaとbの内積を求めます。
実行結果(合計値は正しく出力されていたので省略)
#for文
1.229989767074585
1.1679975986480713
1.2129971981048584
1.244002342224121
1.2080466747283936
1.2040400505065918
1.171039342880249
1.190033197402954
1.4729993343353271
1.1989998817443848
#sum関数
0.663999080657959
0.5890030860900879
0.4519975185394287
0.44500064849853516
0.4510006904602051
0.43799757957458496
0.5030021667480469
0.464000940322876
0.45798826217651367
0.44900035858154297
#内積
0.03200030326843262
0.030002832412719727
0.029001474380493164
0.029003143310546875
0.029993057250976562
0.031000137329101562
0.030005216598510742
0.02900385856628418
0.03000187873840332
0.03100109100341797
最後に
まず、実行結果はAverageを取る必要がないほど明確に内積<sum<forとなりました。しかも割と大差がつきました。この結果だけ見て一概に内積の処理が高速かと言われればそうではなく、要素数が少ないとsumの方が速くなったりもしました。どのような時にsumの方が高速であるかなどは要素数を変えて実験する必要があります。僕はやりません。なぜ内積の方が速くなるのか考えたのですが、全くわからなかったので教えていただきたいです。
今回のような意外なアプローチができるから数学はおもしろいですね。大きなデータを扱うようなPythonプログラマならば知っておいて損はないと思います。参考書の何気ない一文にほんまか!?と疑って検証しようと思ったばかりに多くの時間を費やしましたが知見が広がったのでよしとします。
おわり。参考書↓↓
もしよければ↓ぽちっと↓お願いします。