2016-07-30 2 views
0

Je suis relativement nouveau à Python, mais un peu qualifié au codage. Ce petit bout de code me rend fou. Pourquoi diable est la méthode summe() si têtu dans un fil? Les threads semblent être traités séquentiellement. Cela signifie que chaque thread suivant n'est lancé que si le précédent a pris fin. Je ne sais pas pourquoi? Les quatre fils devraient commencer «parallèlement» et fonctionner «parallèlement». Même s'ils ne s'exécutent que sur un seul Core en raison des restrictions de GIL.Thread informatiquement lourd est "suspendu" en Python 3 - Pourquoi est-ce?

La même procédure avec la méthode count() œuvres "parallèlement" comme prévu.

Cher Internet, s'il vous plaît aidez-moi ...

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() 

Répondre

1

En raison de la GIL, une fonction intégrée comme sum est atomique!; une fois qu'il commence, il ne sera pas interrompu jusqu'à ce qu'il se termine. S'il est possible que le système de thread puisse choisir d'exécuter uniquement la première ligne de summe avant de changer de contexte pour permettre le démarrage du prochain thread, il est hautement improbable. Le "blocage" que vous voyez est sum dans le premier thread bloquant jusqu'à ce qu'il se termine finalement.

Dans count, d'autre part, il n'y a pas une seule longue opération atomique qui bloque sur le GIL; juste beaucoup (et beaucoup, beaucoup et ...) de petites opérations, ce qui donne beaucoup d'opportunités pour démarrer chaque thread et revenir au thread principal. En utilisant une valeur beaucoup plus petite pour n, vous pouvez voir chaque début de fil count, puis quelques instants plus tard, ils se termineront. De même, vous pouvez observer les trois threads summe fonctionnent presque en série (dans un test j'ai couru, le premier a couru à la fin avant de commencer les deux autres fonctionnant en parallèle).

+0

Merci beaucoup pour la réponse très rapide. Mon problème est, la méthode réelle (sum() était juste un exemple) que j'utilise est écrit en Cython, très gros et évidemment atomique aussi. Existe-t-il un moyen de forcer une telle méthode à ne pas être atomique? – Paulquappe

+0

@Paulquappe Il semble que vous fassiez mieux de paralléliser votre fonction Cython. Si vous pouvez vous débarrasser de vos appels d'API Python, vous pouvez libérer le GIL et implémenter la concurrence appropriée en utilisant OpenMP. –

+0

Beaucoup, merci beaucoup. Je pense que cela ressemble à un plan. – Paulquappe