35. GPGPU(General-purpose computing on graphics processing units)
基本的にGPGPUはCUDAでプログラミング
2015年4月3日PyData.Tokyo Meetup #4 35
GPUの演算資源を画像処理以外の目的に応用する技術
by wikipedia
GPGPU
CUDA NVIDIAが提供するGPU向けのC言語の統合開発環境
by wikipedia
注意:データサイエンティストには障壁が高いかも・・・
43. Numba(CPU)
基本的にはデコレータ一発
サポート外のpythonオブジェクトが無ければnopython=Trueでさらに高速化
2015年4月3日PyData.Tokyo Meetup #4 43
@jit('f8[:, :](f8[:, :], f8[:, :])', nopython=True)
def pairwise_distance(X, D):
M = X.shape[0]
N = X.shape[1]
for i in range(M):
for j in range(M):
d = 0.0
for k in range(N):
tmp = X[i, k] - X[j, k]
d += tmp * tmp
D[i, j] = numpy.sqrt(d)
return D
普通のPython 4.69秒
Numba 0.015秒
scipyのpdist 0.007秒
3次元座標の1,000地点間の距離計算時間はこちら
上の実装は、対称行列分の半分はサボれるので納得の結果
44. Cython
3倍速いけど、あんまり速くない。不味いところあったら教えて下さい
2015年4月3日PyData.Tokyo Meetup #4 44
import numpy
cimport numpy
def pairwise_distance(numpy.ndarray[double, ndim=2] X,
numpy.ndarray[double, ndim=2] D):
cdef int i, j, k, M, N
cdef double d, tmp
M = X.shape[0]
N = X.shape[1]
for i in xrange(M):
for j in xrange(M):
d = 0.0
for k in xrange(N):
tmp = X[i, k] - X[j, k]
d += tmp * tmp
D[i, j] = numpy.sqrt(d)
return D
C言語っぽく型を、ひたすら固定 Numbaよりは若干面倒
*.pyxで保存して、import pyximport; pyximport.install()で使う
普通のPython 4.69秒
Cython 1.22秒
3次元座標の1,000地点間の距離計算時間はこちら
49. リスト内包表記
多くの方がご存知の通り、リスト内包表記は早いです
2015年4月3日PyData.Tokyo Meetup #4 49
list_results = []
for i in xrange(1000000):
list_results.append(str(i))
list_results = []
for i in xrange(1000000):
list_results += [str(i)]
list_results = [str(i) for i in xrange(100000)]
リストの足し算するよりも、
appendしたほうが速く
さらに、リスト内包表記の方が速いです
リスト内包表記は『内部的にはappendをせずに、直接リストにぶち込めるから』速いのだそうです。
『リスト内包表記はなぜ速い?』 http://dsas.blog.klab.org/archives/51742727.html
0.42秒
0.35秒
0.26秒
list_results = []
list_results_append = list_results.append
for i in xrange(1000000):
list_results_append(str(i))
さらに、appendのdotを外したほうが速く
0.32秒
list_results = map(str, xrange(100000))
実は、今回の場合はmapが一番速いです。(mapはlambda式とか使うと遅い)
0.13秒
50. 辞書型の活用
データがあるかどうかの探索は、計算時間にかなり効果的
配列を全て走査する線形探索O(n)を理由なくやるのはご法度
2015年4月3日PyData.Tokyo Meetup #4 50
list_elements = [i for i in xrange(10000)]
for i in xrange(10000):
if i in list_elements:
pass
0.87秒
リストに対するin演算は線形探索だが、
辞書に対するin演算はハッシュ探索なのでO(1)で動作
map_elements = {i: None for i in xrange(10000)}
for i in xrange(10000):
if i in map_elements:
pass
0.001秒
気を抜くと、やりがちなので注意が必要
※状況に応じて二分木探索も