2013-05-14 65 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

這可能是由於denormal數字:http://stackoverflow.com/a/9314926/226621 –

+4

在我的測試運行中,只要它開始放緩,我打斷它,並打印numpy.amin(numpy.abs( y [y!= 0]))'並且得到了'4.9406564584124654e-324',所以我認爲反常數是你的答案。我不知道如何從Python內部刷新denormals爲零,除了創建一個C擴展,雖然... –

回答

3

由於@Alok指出,這似乎是由denormal numbers影響性能的情況下造成的。我在我的OSX系統上運行它並確認了這個問題。我不知道在numpy中刷新非規範化爲零的方法。我會嘗試在算法中避開這個問題,避免使用非常小的數字:你是否真的需要劃分y直到達到1.e-324的水平?

如果您避免低數字例如通過添加下面的行放在循環:

y += 1e-100 

那麼你就會有一定的時間每次迭代(因爲額外的操作雖然慢)。另一個解決方法是使用更高精度的算術,例如

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

這會使您的每一步都更加昂貴,但每一步都需要大致相同的時間。

請參見下面的比較在我的系統: enter image description here

+0

_>你真的需要分裂y直到下降到1.e-324水平嗎?是的,否則這些值在大約400次迭代時溢出。我在算法中嘗試了「添加小常量」解決方案(問題中給出的代碼只是一個簡單的測試代碼),它解決了放慢問題。感謝大家的幫助! (特別是@Alok和@tiago) – Ottokar

相關問題