2010-06-10 19 views
5

Musiałem wykonać ciężką operację I/O bound, tj. Analizować duże pliki i konwertować z jednego formatu na inny. Początkowo robiłem to serialnie, tj. Parsowanie jeden po drugim ...! Wydajność była bardzo niska (wykorzystano 90+ sekund). Postanowiłem więc użyć wątków do poprawy wydajności. Stworzyłem jeden wątek dla każdego pliku. (4 wątki)Python wątek i wydajność?

for file in file_list: 
      t=threading.Thread(target = self.convertfile,args = file) 
      t.start() 
      ts.append(t) 
for t in ts: 
      t.join() 

Ale dla mojego zdziwienia, nie ma poprawy wydajności w ogóle. Teraz wykonanie zadania zajmuje około 90 sekund. Ponieważ jest to operacja związana z I/O, oczekiwałem poprawy wydajności.

Odpowiedz

10

W zwykłym tłumaczu Pythona, wątek nie przydzieli więcej rdzeni procesora do twojego programu z powodu global interpreter lock (alias GIL).

Moduł multiprocessing może ci w tym pomóc. (Zauważ, że został wprowadzony w Pythonie 2.6, ale istnieją backporty dla Pythona 2.5).

Jak mówi MSalters, jeśli twój program jest związany z I/O, to jest dyskusyjne, czy jest to użyteczne. Ale to może być warto spróbować :)

Aby osiągnąć co chcesz przy użyciu tego modułu:

import multiprocessing 

MAX_PARALLEL_TASKS = 8 # I have an Intel Core i7 :) 

pool = multiprocessing.Pool(MAX_PARALLEL_TASKS) 

pool.map_async(convertfile, filelist) 

pool.close() 
pool.join() 

Ważne! Funkcja, którą można przekazać do map_async, musi być dostępna do pobrania. Ogólnie rzecz biorąc, metody instancji NIE są dostępne, chyba że je zaprojektujesz! Zauważ, że powyższy convertfile jest funkcją.

Jeśli rzeczywiście potrzebujesz wyników z powrotem z convertfile, istnieją sposoby, aby to zrobić. Przykłady na stronie dokumentacji dotyczącej przetwarzania wieloprocesowego powinny zostać wyjaśnione.

+0

Dzięki delty..Ale moduł do przetwarzania wieloprocesorowego ma własne problemy. 1) Muszę uzupełnić mój kod, ponieważ nie mogę użyć metod instancji .. 2) Mam metodę instancji, która ma wiele obsługi plików. Te procedury obsługi plików są zamknięte w procesach podrzędnych, co jest niedopuszczalne. Muszę więc otworzyć je ponownie. Niestety nie mam możliwości ich poznania, ponieważ są one przekazywane podczas tworzenia instancji – kumar

+0

Nie musi to być sama funkcja konwersji wykonywana w oddzielnym procesie. Czy istnieje sposób, w jaki można wykonać tę instancję w oddzielnych procesach? Na przykład. napisać funkcję lub nawet osobny skrypt, który wykonuje pojedynczą instancję i konwersję; następnie napisz "skrypt główny", który używa modułu wieloprocesorowego do uruchamiania tych funkcji. Oddzielne skrypty można uruchamiać przy użyciu modułu [subprocess] (http://docs.python.org/library/subprocess.html). Jeśli jest wiele wspólnych danych, to tak, to jest, gdzie wieloprocesorowość staje się skomplikowana. Ale w tym module jest o wiele więcej narzędzi :) – detly

2

Nawlekanie umożliwia systemowi przydzielenie większej liczby rdzeni procesora do programu. Jeśli jest to związane I/O, oznacza to, że prędkość była ograniczona przez prędkość susbsystemu I/O zamiast prędkości procesora. W takich przypadkach przydzielanie większej liczby rdzeni procesorów niekoniecznie pomaga - wciąż czeka się na podsystem I/O.

+0

Uważam jednak, że przełączanie wątków ma miejsce, gdy wątek oczekuje na podsystem I/O, prawda? Czynię teraz rzeczy równoległe, co oznacza, że ​​mogę spodziewać się poprawy wydajności? – kumar

+5

Threading w Pythonie nie przydziela więcej rdzeni procesora do programu. – detly

+0

@kumar: Jak mówi odpowiedź, jeśli jesteś związany z I/O - twoje operacje wejścia/wyjścia pracują tak ciężko, jak tylko mogą - więcej czasu procesora lub przetwarzania równoległego nie spowoduje wcześniejszego zakończenia operacji we/wy. – Josh

Powiązane problemy