のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

Pythonで演算をするときはnumpyを使いましょう

Sponsored Links

皆さんこんにちは
お元気ですか。私はそこそこ元気です。

さて、今日はnumpyをオススメしたいと思います。
皆さんリスト内の合計を求める時、どうしていますか?
こんなコードを書いていないでしょうか・・・・・・?

for i in xrange(N):
    sum += list[i]

これは色んな意味でやめましょう。

理由は3つ
1.わかりにくい
そりゃぱってコード見た時一瞬何してるのか考えますよね
2.遅い
listなどを使うと非常に遅い。ということでnumpyを使いましょう
3.もし、listをnumpy.arrayのオブジェクトを利用していれば遅すぎて泣きそうになる
理由はわかりませんが(想像はつくけど)numpy.arrayを使うとアクセス速度が非常に遅く
非常に遅いです。

実際にどれくらい差があるかを気になりませんか?私、きになり(ry
今回はnumpy.sumを利用して検証したいと思います。

実験環境

OS:X 10.9.2
CPU:2.8GHz IntelCore i7
メモリ:16GB 1600MHz DDR3

実験のケース

1.listを回して計算する
2.listをnumpy.sumに渡す
3.numpy.arrayで変換したものをnumpy.sumに渡す
4.numpy.arrayのループ

長さ10000000、回数10回の平均

ソースコード

import numpy as np
import time

Time = 10
N = 10000000
def list_sum(array):
	for i in xrange(Time):
		result = 0
		for j in xrange(len(array)):
			result += array[j]

def list_array_sum(array):
	for i in xrange(Time):
		np.sum(array)

def numpy_array_sum(array):
	for i in xrange(Time):
		np.sum(array)

def numpy_array_sum_element(array):
	for i in xrange(Time):
		result = 0
		for j in xrange(len(array)):
			result += array[j]

if __name__ == '__main__':
	array = [i for i in xrange(N)]
	list_array = [array,array,np.array(array),np.array(array)]
	list_function = [list_sum,list_array_sum,numpy_array_sum,numpy_array_sum_element]

	for array,function in zip(list_array,list_function):
		start = time.time()
		function(array)
		print (time.time() - start) / Time

実験結果

実験 速度
リスト回し 0.618385314941
numpy.sum(list) 1.04538609982
numpy.sum(numpy.array) 0.00696699619293
アクセス(numpy.array) 4.51080038548

どうやらlistを渡すと型変換を行い、内部で計算しているのではないでしょうか。
因みに計測をすると型を変換するのに(numpy.array)0.0248320102692秒でした。足しても全然合わないので他にも何かやっているのでしょうか(コピーとか)。
うん、やっぱりnumpyを使うほうが早かった。というか圧倒的すぎて笑うしかない・・・

ただ、下手にlistを渡すぐらいなら、自分で計算したほうが早いので事前に変換しておくことを忘れないようにしましょう