34 votes

Les pools de threads sont-ils nécessaires pour le code Haskell pur ?

En Real World Haskell, chapitre 28, mémoire transactionnelle logicielle un vérificateur de liens web simultané est développé. Il récupère tous les liens d'une page Web et envoie une requête HEAD à chacun d'entre eux pour savoir si le lien est actif. Une approche concurrente est adoptée pour construire ce programme et la déclaration suivante est faite :

Nous ne pouvons pas simplement créer un thread par URL, car cela pourrait surcharger notre CPU ou notre connexion réseau si (comme nous le pensons) la plupart des liens sont actifs et réactifs. Au lieu de cela, nous utilisons un nombre fixe de fils de travail, qui récupèrent les URL à télécharger à partir d'une file d'attente.

Je ne comprends pas bien pourquoi ce pool de threads est nécessaire au lieu d'utiliser forkIO pour chaque lien. À ma connaissance, le moteur d'exécution Haskell maintient un pool de threads et les planifie de manière appropriée, de sorte que je ne vois pas de surcharge pour le CPU. En outre, dans une discussion sur la concurrence sur la liste de diffusion Haskell J'ai trouvé la déclaration suivante qui va dans le même sens :

Le seul paradigme qui n'a pas de sens en Haskell est celui des threads de travail (puisque le RTS le fait). pour nous) ; au lieu d'aller chercher un worker, il suffit de forkIO à la place.

Le pool de threads est-il seulement nécessaire pour la partie réseau ou y a-t-il une raison CPU pour cela aussi ?

23voto

sclv Points 25335

Le problème central, j'imagine, est le côté réseau. Si vous avez 10 000 liens et une fourchette pour chaque lien, vous avez potentiellement 10 000 sockets que vous essayez d'ouvrir en même temps, ce qui, selon la configuration de votre OS, ne sera probablement pas possible, et encore moins efficace.

Cependant, le fait que nous ayons des threads verts qui sont "virtuellement" planifiés à travers de multiples os threads (qui sont idéalement collés à des cœurs individuels) ne signifie pas non plus que nous pouvons distribuer le travail de manière aléatoire sans tenir compte de l'utilisation du processeur. Le problème ici n'est pas tant que l'ordonnancement du CPU lui-même ne sera pas géré pour nous, mais plutôt que les changements de contexte (même les verts) coûtent des cycles. Chaque thread, s'il travaille sur des données différentes, aura besoin de faire entrer ces données dans le processeur. S'il y a assez de données, cela signifie tirer des choses dans et hors du cache du processeur. Même sans cela, cela signifie tirer des choses du cache vers les registres, etc.

Même si un problème est trivialement parallèle, il est virtuellement jamais la bonne idée de tout fractionner au maximum et d'essayer de tout faire en même temps.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X