2016-10-31 18 views
8

muszę przyspieszyć następujący kod:Jak mogę przyspieszyć ten dwuliniowy kod?

for i in range(0, 2**N): 

    output[i] = f(np.array(map(int, bin(i)[2:].zfill(N)))) 

N wynosi około 30, więc kod jest bardzo powolny (trwa około 33 godzin na moim laptopie). Argument funkcji f() jest binarną reprezentacją indeksu i, a f() może być dowolną funkcją, która można wektoryzować. Nie jestem ekspertem, ale żeby przyspieszyć kod, pomyślałem o pozbyciu się pętli for, co oznacza, że ​​muszę wektoryzować argument f(). Innymi słowy, muszę utworzyć macierz z binarnymi reprezentacjami liczb od 0 do 2**N. Można to osiągnąć poprzez następujący kod:

list(itertools.product([0, 1], repeat=N)) 

że znalazłem w this link. Jednak wydaje mi się, że itertools jest bardzo powolny i wyraźnie zajmuje dużo pamięci, ponieważ 2**30 ma około miliarda.

Czy mają Państwo jakieś sugestie, aby przyspieszyć ten kod? Z góry dziękuję.

+0

Wydaje się, że wyrzucasz wszystkie oprócz ostatniej wartości 'wyjścia'. – user2357112

+8

Zamiast tworzenia miliardowej tablicy elementów, czemu nie przepisać ponownie jako generatora? – dawg

+0

Wyszukaj generatory i komendę 'yield'. – oliversm

Odpowiedz

6

profil Zawsze:

>>> timeit.timeit("for i in range(0, 2**N): numpy.array(map(int, bin(i)[2:].zfill(N)))", "import numpy; N=5", number=100000) 
26.472519159317017 
>>> timeit.timeit("for t in itertools.product((0, 1), repeat=N): numpy.array(t)", "import numpy, itertools; N=5", number=100000) 
6.129688024520874 

Można zobaczyć, że metoda itertools.product jest znacznie szybszy, ponieważ nie musi bawić się wokół ze strun.

Problem może być jednak taki, że większość czasu spędza się w funkcji f.

Innym rozwiązaniem może być zaakceptowanie liczby całkowitej przez f i użycie jej jako pola binarnego.

+0

Dodatkowo: Czas na 2^24 operacji "pass" na ostatnim MBP: 883 ms z samym 'range', 501ms z' xrange', 1,92s z wywołaniem funkcji 'pass' i' range' oraz 1,58s dla funkcji call + 'xrange'. –

+0

Fajnie, próbowałem z 'N = 20' i zajmuje to 1 minutę zamiast 1,5 minuty. Pozwoli to zaoszczędzić dużo czasu na większe 'N'. Chyba 22 godziny vs 33 dla 'N = 30'. – user2983638