2015-04-17 15 views
5

Załóżmy, że mam wątek i główną część programu. Z powodu GIL, jeden wątek powinien działać w odpowiednim czasie (a nie symulacyjnie)? Ale co, jeśli jeden z wątków jest nieskończoną pętlą (lub obaj o to chodzi)?Nici w pythonach i GIL

Czy te dwa procesy przebiegałyby równolegle?

def test(): 
     while True: 
      print "hello" 

    def test2(): 
     while True: 
      print "hi" 

    def start_thread(): 
     try: 
      thread.start_new_thread(test2,()) 
     except: 
      print "Error: Unable to start thread" 
    start_thread() 
    test() 
+0

Nie dzwonisz do start_thread w dowolnym miejscu? – ZdaR

+0

Ten kod był tylko dla celów ilustracyjnych lol Niestety, właśnie dodałem linię kodu, która rozpoczyna wątek –

Odpowiedz

6

Będą biec równolegle, ale nie faktycznie w równoległego. System operacyjny będzie często przełączał się pomiędzy tymi dwoma wątkami, aby obaj mogli wykonać swoją pracę. To właśnie oznacza "współbieżny"; jeden wątek nie musi czekać na zakończenie drugiego, zanim zacznie działać. Ale z powodu GIL, oni nigdy nie będą obaj biegać dokładnie w tym samym czasie, gdzie każdy jest prowadzony na innym rdzeniu równolegle. Każdy wątek będzie działał przez chwilę, zatrzyma się, gdy drugi wątek będzie działał, a następnie zacznie znowu działać, a następnie przerwie, itp.

To wystarczy, aby zobaczyć, czy wystarczy uruchomić przykładowy kod. Oto dane wyjściowe na moim komputerze:

hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 
hello 
hi 

Najwyraźniej oba wątki są uruchomione. Każdy wątek działa wolniej, niż gdyby był uruchomiony tylko jeden wątek w programie.

Rozważmy następujący przykład, gdzie każdy wątek oblicza ciągu Fibonacciego:

import thread 
import time 


def fib(n): 
    if n <= 1: 
     return n 

    return fib(n-1) + fib(n-2) 

def test(): 
    while True: 
     start = time.time() 
     out = fib(32) 
     print "hello %s: %s" % (out, str(time.time() - start)) 

def test2(): 
    while True: 
     out = fib(20) 

def start_thread(): 
    try: 
     thread.start_new_thread(test2,()) 
    except: 
     print "Error: Unable to start thread" 
#start_thread() 
test() 

Wystarczy test działa (więc nie drugi wątek), otrzymuję ten wynik:

hello 2178309: 0.953778982162 
hello 2178309: 0.954975128174 
hello 2178309: 0.95578789711 
hello 2178309: 0.949182033539 

Jeśli zacznę się test2 również w tle, otrzymuję to:

hello 2178309: 4.07990288734 
hello 2178309: 4.08523893356 
hello 2178309: 2.51651597023 
hello 2178309: 2.13291287422 
hello 2178309: 2.19885015488 

Jak widać, wydajność ma ogromny hit.

Zauważ, że jeśli jeden z wątków robi coś, co uwalnia blokujące GIL-podobne operacje wejścia-wyjścia lub wywoływania w bibliotece C, która uwalnia GIL-a, nie zobaczysz tego rodzaju pogorszenia wydajności, ponieważ w tym przypadku przypadku oba wątki faktycznie mogą działać równolegle. Nie dotyczy to powyższego przykładu, ponieważ żaden wątek nie wykonuje pracy, która uwalnia GIL.

+0

Widzę ... Dzięki. O ile wolniej będzie działał? Czy to jest krytyczne? Załóżmy, że uruchomiłem program dla giełdy, jeden wątek odbiera dane od brokera, a drugi wątek wykonuje zamówienia. Opóźnienie powinno być tak niskie, jak to możliwe (maksymalnie milisekundy). Czy to nadal działa? –

+0

@LuisCruz To zależy trochę od każdego wątku. W dwóch programach z gwintem, w których jeden blokuje głównie operacje wejścia/wyjścia, a drugi wykonuje obliczenia, nie powinno to być * straszne *, ale za każdym razem, gdy pojawi się żądanie, będzie pewna kara. Zwykle w Pythonie pojawi się proces w tle użycie "przetwarzania wieloprocesorowego" do obsługi obliczeń, o ile obciążenie związane z IPC nie przewyższa korzyści unikania GIL. Ale jeśli chcesz, aby wiele wątków wykonywało obliczenia, zdecydowanie powinieneś używać procesów. – dano

+0

Wielkie dzięki za informacje. W moim przypadku jeden wątek czyta nazwany potok, więc jeśli nie ma danych, zostanie zablokowany. Drugi wątek odbiera dane z brokera za pośrednictwem interfejsu websocket API. Więc w moim przypadku wątki nie powinny być zbyt złe, tak przypuszczam. –