いくつかのフーリエ変換に基づいたモデルのコードを作成しています。現在、私はその一部を最適化しようとしているので、いくらかの大量のデータでも使用できるようになっています。それをしようとしている間、私は奇妙な振る舞いを見つけました、主に私のコードのループバージョンは、numpyで書かれた同じコードより速くなっています。次のようにテストコードは次のとおりです。Pythonのループがnumpyの配列操作よりも速くなる
# -*- coding: utf-8 -*-
import numpy as np
import timeit
def fourier_coef_loop(ts, times, k_max):
coefs = np.zeros(k_max, dtype=float)
t = 2.0 * np.pi * (times - times[0])/times[-1]
x = np.dot(np.arange(1,k_max+1)[np.newaxis].T,t[np.newaxis])
for k in xrange(1, k_max + 1):
cos_k = np.cos(x[k-1])
coefs[k - 1] = (ts[-1] - ts[0]) + (ts[:-1] * (cos_k[:-1] - cos_k[1:])).sum()
return(coefs)
def fourier_coef_np(ts, times, k_max):
coefs = np.zeros(k_max, dtype=float)
t = 2.0 * np.pi * (times - times[0])/times[-1]
x = np.dot(np.arange(1,k_max+1)[np.newaxis].T,t[np.newaxis])
coefs = np.add(np.einsum('ij,j->i',np.diff(np.cos(x)), -ts[:-1]), (ts[-1] - ts[0]))
return(coefs)
if __name__ == '__main__':
iterations = 10
size = 20000
setup = "from __main__ import fourier_coef_loop, fourier_coef_np, size\n" \
"import numpy as np"
# arg = np.random.normal(size=size)
# print(np.all(fourier_coef_np(arg, np.arange(size,dtype=float), size/2) == fourier_coef_loop(arg, np.arange(size,dtype=float), size/2)))
time_loop = timeit.timeit("fourier_coef_loop(np.random.normal(size=size), np.arange(size,dtype=float), size/2)",
setup=setup, number=iterations)
print("With loop: {} s".format(time_loop))
time_np = timeit.timeit("fourier_coef_np(np.random.normal(size=size), np.arange(size,dtype=float), size/2)",
setup=setup, number=iterations)
print("With numpy: {} s".format(time_np))
それは次のような結果を与える:ループバージョンはより速く、純粋にnumpyのバージョンよりも、なぜ
With loop: 60.8385488987 s
With numpy: 64.9192998409 s
誰かが私に教えていただけますか?私は完全にアイデアがなくなった。この特定の機能をより速くする方法に関する提案もありがとう。
あなたはループとベクトル化されたバージョンのタイミングを取っているわけではありません。擬似乱数法をたくさん生成することを含む大きな混乱を繰り返すでしょう。さらに、コードは高度に最適化されていません。例えば、 'einsum( 'ij、j-> i、...)'は、行列 - ベクトル積( - > 'np.dot')や' x = np.dot arange(1、k_max + 1)[np.newaxis] .T、t [np.newaxis]) 'を実行すると、よりクリーンな方法があるはずです。 –
時間はそれほど違いはありません。そのサイズを使用しようとすると、私はメモリエラーが発生します。サイズ= 2000の場合、タイミングも同様です。 200の場合、npバージョンはかなりのエッジを持っています。だから私の推測では、より大きなサイズのメモリ管理の問題は、 'numpy'時間に噛み砕いているということです。 – hpaulj
@hpaulj私は、それらのタイミングが、ループをベクトル化されたバージョンと比較するのに関連しているとは思っていません。 –