Próbuję zoptymalizować mój kod przy użyciu modułu Pythona multiprocessing.Pool
, ale nie otrzymuję wyników przyśpieszenia, których logicznie oczekiwałbym.Wieloprocesorowe przetwarzanie w języku Python nie przyspiesza oczekiwanie
Główna metoda, którą wykonuję, polega na obliczaniu produktów macierzy-wektorów dla dużej liczby wektorów i stałej dużej macierzy rzadkiej. Poniżej znajduje się przykład zabawki, który wykonuje to, czego potrzebuję, ale z losowymi matrycami.
import time
import numpy as np
import scipy.sparse as sp
def calculate(vector, matrix = None):
for i in range(50):
v = matrix.dot(vector)
return v
if __name__ == '__main__':
N = 1e6
matrix = sp.rand(N, N, density = 1e-5, format = 'csr')
t = time.time()
res = []
for i in range(10):
res.append(calculate(np.random.rand(N), matrix = matrix))
print time.time() - t
Sposób kończy się w ciągu około 30
sekund.
Teraz, ponieważ obliczenia każdego elementu z results
nie zależy od wyników jakichkolwiek innych obliczeń, naturalne jest, że obliczenia równoległe przyspieszą proces. Chodzi o to, aby utworzyć 4 procesy i jeśli każdy wykona część obliczeń, czas potrzebny na ukończenie wszystkich procesów powinien zmniejszyć się o około jeden czynnik około 4
. Aby to zrobić, napisałem poniższy kod:
import time
import numpy as np
import scipy.sparse as sp
from multiprocessing import Pool
from functools import partial
def calculate(vector, matrix = None):
for i in range(50):
v = matrix.dot(vector)
return v
if __name__ == '__main__':
N = 1e6
matrix = sp.rand(N, N, density = 1e-5, format = 'csr')
t = time.time()
input = []
for i in range(10):
input.append(np.random.rand(N))
mp = partial(calculate, matrix = matrix)
p = Pool(4)
res = p.map(mp, input)
print time.time() - t
Moim problemem jest to, że kod ten trwa nieco ponad 20
sekund do uruchomienia, więc nie miałem nawet zwiększyć wydajność o czynnik 2
! Co gorsza, wydajność poprawia się, nawet jeśli pula zawiera procesy ! Masz pomysł, dlaczego przyspieszenie się nie dzieje?
Uwaga: Moja rzeczywista metoda trwa znacznie dłużej, a wektory wejściowe są przechowywane w pliku. Jeśli podzielę plik na części 4
, a następnie uruchomię mój skrypt w oddzielnym procesie dla każdego pliku ręcznie, każdy proces zakończy się cztery razy szybciej niż w przypadku całego pliku (zgodnie z oczekiwaniami). Ja confuzed dlaczego ta prędkość-up (co jest oczywiście możliwe) nie dzieje się z multiprocessing.Pool
Edi: Właśnie dowiedziałem Multiprocessing.Pool makes Numpy matrix multiplication slower to pytanie, które może być związane. Muszę jednak sprawdzić.
Pytanie: Ile fizycznych rdzeni procesora (bez hiperwątkowości) ma system, na którym to działa? –
@KlausD. Fizycznie mam rdzenie "4". Właśnie dlatego ręcznie dzielę ten plik na fragmenty "4", a nie "8". – 5xum
Jeśli umieścisz kilka testów porównawczych 'time.time()' w swojej metodzie 'calculate', zobaczysz, że 50-kropkowe połączenia są prawie 4 razy dłuższe niż w przypadku nierównoległym. Nie wiem dlaczego, ponieważ narzędzia takie jak "top" sprawiają, że przypadek nierównolegania wykorzystuje tylko jeden procesor, podczas gdy równoległy przypadek sprawia, że 4 procesory są w pełni wykorzystywane. –