2013-05-14 7 views
12

以下のコードは、私が現在実施していたアルゴリズムで発生した問題を再現:反復的な要素ごとの配列の乗算がnumpyで遅くなるのはなぜですか?

import numpy.random as rand 
import time 

x = rand.normal(size=(300,50000)) 
y = rand.normal(size=(300,50000)) 

for i in range(1000): 
    t0 = time.time() 
    y *= x 
    print "%.4f" % (time.time()-t0) 
    y /= y.max() #to prevent overflows 

問題は、一回の反復が複数回以上をとるまで、繰り返しのいくつかの番号の後に、物事がだんだん遅くし始めるということです時間よりも早い。

Pythonのプロセスによって減速 enter image description here

CPU使用率のプロットは、安定した周りの17から18パーセントを全体の時間です。

私が使用している:

  • のPython 2.7.4 32ビット版を、
  • Numpy 1.7.1 with MKL;
  • のWindows 8
+0

私はLinuxでのpython-2.7.4でこの動作を参照してくださいとは思いません。 –

+9

これはおそらく非正規化数のためです:http://stackoverflow.com/a/9314926/226621 –

+4

私のテストでは、スローダウンが始まるとすぐに中断し、 'numpy.amin(numpy.abs(numpy.abs y [y!= 0])) 'と' 4.9406564584124654e-324'を得たので、非正規数があなたの答えだと思います。私はPythonの中でdenormalsを0にする方法を知らないのですが、Cの拡張を作成する以外には... –

答えて

3

@Alokが指摘したように、これはパフォーマンスに影響を与えることdenormal numbersによって引き起こされているように見えます。私はOSXシステムでそれを実行し、問題を確認しました。デノーマルをゼロにする方法を知らない。私は非常に小さな数字を避けることによってアルゴリズムでこの問題を回避しようとします:それは1.e-324レベルになるまで、yを本当に分割する必要がありますか?

数字が小さくなることを避けると、あなたのループに次の行追加して:

y += 1e-100 

を、あなたは(あるため、余分な動作を遅くいえ)繰り返しごとに一定の時間を持っています。もう1つの回避策は、より高精度の石膏を使用することです。

x = rand.normal(size=(300,50000)).astype('longdouble') 
y = rand.normal(size=(300,50000)).astype('longdouble') 

これにより、それぞれのステップが高価になりますが、各ステップはほぼ同じ時間がかかります。

は私のシステムでは、次の比較を参照してください。 enter image description here

+0

_>これは1.e-324レベルになるまで本当にyを分割する必要がありますか?そうでなければ、値は約400回の繰り返しでオーバーフローします。私は私のアルゴリズム(質問に与えられたコードは単純なテストコードに過ぎない)に小さな定数を加えることを試してみました。それは減速の問題を解決しました。あなたの助けをありがとう! (特に@Alokと@tiago) – Ottokar

関連する問題