Un modèle que j'ai rencontré un certain nombre de fois maintenant est celui où une liste de valeurs doit être vérifiée en mappant un test dessus et en voyant si certains ou tous les éléments ont réussi. La solution typique consiste simplement à utiliser les fonctions intégrées all
et any
.
Le problème est que ceux-ci sont évalués en série. Dans de nombreux cas, il serait beaucoup plus rapide d'évaluer en parallèle avec le processus étant terminé une fois qu'un thread trouve un "False" pour all
ou un "True" pour any
. Je suis à peu près sûr que le comportement de court-circuit ne peut pas être implémenté à l'aide de Control.Parallel car il nécessite une communication inter-processus et je ne comprends pas assez près de Control.Concurrent pour l'implémenter.
C'est un modèle assez courant en mathématiques (par exemple Miller-Rabin Primality), donc j'ai l'impression que quelqu'un a probablement déjà trouvé une solution pour cela, mais pour des raisons évidentes, faire une recherche Google pour "parallèle ou / et / tout / tout sur la liste" haskell "ne renvoie pas beaucoup de résultats pertinents.
la source
unamb
bibliothèquepthreads
en C ou les threads verts dans Haskell) Vous ne démarrez pas plusieurs serveurs Web afin de gérer les requêtes Web simultanées, au lieu de cela, vous exécutez plusieurs threads en un seul processus! Il en va de même pour le parallélisme. Vous faites tourner autant de threads que vous avez de CPU et répartissez votre travail de manière égale, prenant ainsi en charge les tâches liées au CPU. Essayez cette bibliothèque pour vous convaincre github.com/lehins/haskell-schedulerRéponses:
Dans de nombreux programmes réalistes, vous pouvez utiliser des stratégies parallèles à cet effet. En effet, même s'il n'existe aucun mécanisme explicite pour annuler les calculs inutiles, cela se produira implicitement lorsque le garbage collector s'exécute. À titre d'exemple concret, considérons le programme suivant:
Il utilise une stratégie de liste parallèle pour rechercher
waldo = 0
(qui ne sera jamais trouvée) dans la sortie de 100 flux PRNG de 40 millions de numéros chacun. Compilez-le et exécutez-le:et il accroche quatre cœurs pendant environ 16 secondes, puis imprime
False
. Notez dans les statistiques que les 100 étincelles sont "converties" et donc exécutées jusqu'à la fin:Maintenant, changez
waldo
pour une valeur qui peut être trouvée tôt:et modifiez
main
pour garder le fil vivant pendant 10 secondes:Vous remarquerez qu'il s'imprime
True
presque immédiatement, mais 4 cœurs restent ancrés à 100% du processeur (au moins pendant un petit moment), illustrant que les calculs inutiles continuent de fonctionner et ne sont pas court-circuités, comme vous auriez pu le craindre.MAIS , les choses changent si vous forcez un ramasse-miettes après avoir obtenu la réponse:
Maintenant, vous verrez que le CPU devient inactif peu de temps après l'impression
True
, et les statistiques montrent que la plupart des calculs ont été récupérés avant de s'exécuter:Dans les programmes réalistes, un explicite
performGC
ne sera pas nécessaire, car les GC seront effectués régulièrement de manière régulière. Certains calculs inutiles continueront de s'exécuter une fois la réponse trouvée, mais dans de nombreux scénarios réalistes, la fraction des calculs inutiles ne sera pas un facteur particulièrement important.En particulier, si la liste est longue et que chaque test individuel d'un élément de liste est rapide, les stratégies parallèles auront d'excellentes performances dans le monde réel et sont faciles à mettre en œuvre dans le marché.
la source