2013-05-14 10 views
12

Poniższy kod odtwarza Mam problem napotkany w algorytmie jestem obecnie wykonawcze:Dlaczego iteracyjne mnożenie macierzy elementowej spowalnia w 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 

Problemem jest to, że po pewnej liczbie iteracji, sprawy zaczynają się stopniowo wolniej aż jedna iteracja trwa kilka razy więcej czas niż początkowo.

Działka spowolnienia enter image description here

wykorzystanie procesora w procesie Python stałym poziomie około 17-18% przez cały czas.

Używam:

  • Python 2.7.4 w wersji 32-bitowej;
  • Numpy 1.7.1 z MKL;
  • Windows 8.
+0

Nie sądzę widzę ten problem z python-2.7.4 pod Linuksem. –

+9

Jest to prawdopodobnie spowodowane liczbami denormalnymi: http://stackoverflow.com/a/9314926/226621 –

+4

W moim teście uruchomionym, gdy tylko zaczęło zwalniać, przerywam go i 'print numpy.amin (numpy.abs (y [y! = 0])) 'i ma' 4.9406564584124654e-324', więc myślę, że denormalne liczby są twoją odpowiedzią. Nie wiem, jak wypłukać denormały do ​​zera z poziomu Pythona innego niż tworzenie rozszerzenia C ... –

Odpowiedz

3

Jak @Alok wskazał, wydaje się to być spowodowane denormal numbers wpływ na wydajność. Uruchomiłem go na moim systemie OSX i potwierdziłem problem. Nie znam sposobu na spłukanie denormałów do zera w trybie numpy. Chciałbym spróbować obejść ten problem w algorytmie, unikając bardzo małych liczb: czy naprawdę trzeba dzielić y, aż osiągnie poziom 1.e-324?

Jeśli unikniesz niskiej liczby, np. przez dodanie następującej linii w pętli:

y += 1e-100 

wtedy będziesz miał stały czas za iteracji (choć wolniej ze względu na dodatkowe działania). Innym obejściem jest użycie arytmetyki o wyższej precyzji, np.

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

Spowoduje to, że każdy z twoich kroków droższe, ale każdy krok ma mniej więcej tyle samo czasu.

Zobacz następujący porównania w moim systemie: enter image description here

+0

_> Czy naprawdę musisz dzielić y, aż osiągnie poziom 1.e-324? _ Tak, w przeciwnym razie wartości przekroczą około 400 iteracji. Próbowałem "dodawać małe stałe" rozwiązanie w moim algorytmie (kod podany w pytaniu to tylko prosty testcode) i rozwiązał problem spowolnienia. Dziękuję wszystkim za pomoc! (szczególnie @Alok i @tiago) – Ottokar