2016-07-30 12 views
0

Ich bin relativ neu in Python, aber ein wenig geschickt in der Codierung. Dieses kleine Stück Code macht mich verrückt. Warum in aller Welt ist die Methode summe() so stur in einem Thread? Die Threads scheinen der Reihe nach verarbeitet zu werden. Das heißt, jeder nächste Thread wird nur gestartet, wenn der vorherige beendet ist. Ich weiß nicht warum? Alle vier Threads sollten "parallel" starten und "parallel" arbeiten. Auch wenn sie aufgrund der Einschränkungen von GIL nur auf einem einzelnen Core laufen.Rechnerisch schwerer Thread hängt in Python 3 - Warum ist das?

Das gleiche Verfahren mit dem Verfahren count() Werke "parallel", wie beabsichtigt.

Lieber Internet, bitte helfen Sie mir ...

Paul :)

#!/usr/bin/python3 

import threading 

# Hanging... 
def summe(n): 
    print("Start") 
    s = sum(range(n)) 
    print("Done") 

# Works like a charm 
def count(n): 
    print("Start") 
    while n > 0: 
     n = n-1 
    print("Done") 

# This works 
for i in range(3): 
    threading.Thread(target=count,args=(10000000000000,)).start() 

# This hangs... 
for i in range(3): 
    threading.Thread(target=summe,args=(10000000000000,)).start() 

Antwort

1

Aufgrund der GIL, eine eingebaute Funktion wie sum ist atomar!; Sobald es beginnt, wird es nicht unterbrochen, bis es abgeschlossen ist. Während es möglich ist, dass das Threading-System wählen konnte, nur die erste Zeile von summe vor Kontextwechsel auszuführen, damit der nächste Thread gestartet werden kann, ist es sehr unwahrscheinlich. Das "Hängen", das Sie sehen, ist sum in der ersten Threadblockierung, bis es schließlich beendet wird.

In count, auf der anderen Seite, gibt es keine lange eine atomare Operation, dass die Blöcke auf der GIL; einfach viele (und viele, viele und ...) kleine Operationen, die viele Möglichkeiten bieten, jeden Thread zu starten und zum Hauptthread zurückzukehren. Mit einem viel kleineren Wert für n können Sie jeden Thread starten count, dann ein paar Momente später werden sie abgeschlossen. Ebenso können Sie die drei Threads sehen, die nahezu seriell ausgeführt werden (in einem Test lief ich, der erste lief bis zum Ende, bevor ich die anderen zwei parallel laufen ließ).

+0

Vielen Dank für die sehr schnelle Antwort. Mein Problem ist, die echte Methode (sum() war nur ein Beispiel) Ich benutze ist in Cython geschrieben, sehr groß und offensichtlich auch atomar. Gibt es eine Möglichkeit, eine solche Methode nicht atomar zu machen? – Paulquappe

+0

@Paulquappe Klingt so, als ob Sie Ihre Cython-Funktion besser parallelisieren könnten. Wenn Sie Ihre Python-API-Aufrufe loswerden können, können Sie die GIL freigeben und die korrekte Parallelität mit OpenMP implementieren. –

+0

Vielen, vielen Dank. Ich denke, das klingt nach einem Plan. – Paulquappe