2017-05-10 6 views
7

私は、ログ関数(整数用)を多用し、何十億もの呼び出しを行う計算プロジェクトを持っています。私はnumpyのログのパフォーマンスが驚くほど遅いことを知っています。numpyのログ機能はどうなりますか?パフォーマンスを改善する方法はありますか?

次のコードは、完了するまでに15〜17秒を要し:

import numpy as np 
import time 

t1 = time.time() 
for i in range(1,10000000): 
    np.log(i) 
t2 = time.time() 
print(t2 - t1) 

しかし、math.log関数は3〜4秒からはるかに少ない時間を要します。

import math 
import time 

t1 = time.time() 
for i in range(1,10000000): 
    math.log(i) 
t2 = time.time() 
print(t2 - t1) 

私もmatlabとC#をテストしました。これは、それぞれ約2秒とわずか0.3秒かかる。

MATLAB

tic 
for i = 1:10000000 
    log(i); 
end 
toc 

C#

var t = DateTime.Now; 
for (int i = 1; i < 10000000; ++i) 
    Math.Log(i); 
Console.WriteLine((DateTime.Now - t).TotalSeconds); 

私は、ログ機能のパフォーマンスを向上させることができますPythonでどのような方法はありますか?

+0

私はその答えにかなり興味があります。私はちょうどソースコードに入ったので、特に関数をトレースすることは困難です。ソースコードの左側には、次のように書かれています。 __doc__から復元されました。誰でもソースコードの仕組みを説明できますか? –

+1

答えはここにあるようですhttp://stackoverflow.com/questions/3650194/are-numpys-math-functions-faster-than-pythons?rq=1 – Bathsheba

+9

'np.log'は、以下の配列で動作するように最適化されています。単一の値ではなく、値。たとえば、 'np.log(np.arange(1,10000000))'(その範囲の整数の配列のログ)は私にとって約120msかかります。 –

答えて

2

NumPys関数は、単一値またはスカラーではない配列用に設計されています。大規模な配列では速度を向上させるためにいくつかのチェックと変換を行うため、オーバーヘッドがかなり高くなりますが、これらはスカラーにとって高価です。一方

>>> import numpy as np 
>>> import math 

>>> type(np.log(2.)) 
numpy.float64 
>>> type(math.log(2.)) 
float 

math -moduleがスカラーのために最適化されています

変換を使用すると、戻り値の種類をチェックすると、実際には明白です。だから、彼らは多くの小切手を必要としません(私はただ2つしかないと思います:floatに変換し、それが<= 0です)。だからmath.lognumpy.logと比較してスカラー用のがより速いです。

しかし、あなたが配列を操作していて、配列NumPyのすべての要素の対数を取りたい場合、はるかに高速になります。私のコンピュータ上のアレイ上のnp.logの実行は、リスト内の各項目のmath.logに比べて私の時間は、その後のタイミングが異なって見える場合:

arr = np.arange(1, 10000000) 
%timeit np.log(arr) 
201 ms ± 959 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) 

lst = arr.tolist() 
%timeit [math.log(item) for item in lst] 
8.77 s ± 63.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) 

のでnp.logは、アレイ上で速く桁違いになります(それはより多くのですこの場合は40倍速くなります)!そして、自分でループを書く必要はありません。 ufunc np.logも多次元numpy配列でも正しく動作し、その場で操作を行うこともできます。

大まかには、数千のアイテムを持つ配列を持つ場合、スカラーまたは数十個のアイテムがある場合はNumPyが速くなります。math +明示的なループが高速になります。


タイミングコードにはtimeも使用しないでください。そこより正確な結果が得られた専用のモジュールがあり、より良い統計とタイミングの間にガベージコレクションを無効にします。

  • timeit(ビルトイン)
  • perf(拡張パッケージ)

私は、一般的に%timeitを使用しますこれはtimeit機能の便利なラッパーですが、IPythonが必要です。彼らはすでに結果の平均と偏差を便利に表示し、 "最高の7"または "最高の3"の結果を表示するような(ほとんど)有用な統計を行います。


私は最近、いくつかの点でも、ここで適用され、another questionためにnumpyの機能の実行時の動作を分析しました。

1

興味深いことに、遅いPython標準ライブラリの問題は、私のマシン(Windows 10、Python 2.7.11およびnumpy 1.11.0を実行中)では複製されません。

>>> t1 = time.time() 
>>> for i in range(1,10000000): 
>>>  _ = np.log(i) 
>>> t2 = time.time() 
>>> print(t2 - t1) 
9.86099982262 
>>> t1 = time.time() 
>>> for i in range(1,10000000): 
>>>  _ = math.log(i) 
>>> t2 = time.time() 
>>> print(t2 - t1) 
2.48300004005 

Matlabのパフォーマンスに似ています。 @Nilsは良い点を挙げていますが、numpyは配列上で効率的になるように設計されています。

>>> t1 = time.time() 
>>> for i in range(1,1000): 
>>>  _ = np.log(np.arange(1,10000)) 
>>> t2 = time.time() 
>>> print(t2 - t1) 
0.146000146866 
>>> t1 = time.time() 
>>> for i in range(1,1000): 
>>>  _ = [math.log(i) for i in range(1,10000)] 
>>> t2 = time.time() 
>>> print(t2 - t1) 
2.3220000267 

入力をベクトル化することができれば、numpyは標準の数学ライブラリより優れており、さらにC#に近づくことさえあります。

関連する問題