J'essaie d'apprendre à utiliser le module J'essaie d'exécuter le code suivant ( fibs.hs em>). p> i compilé ceci avec: p> et puis je reçois Les résultats suivants exécutant ce programme (sortie d'un script Python qui exécute chaque programme 100 fois et renvoie l'écart moyen et type de l'heure d'exécution): p> Mes questions sont: p> Qu'est-ce qui se passe exactement lorsque j'évalue: p>
Control.parallallel code>, mais je pense que je ne l'ai pas fait correctement.
a `par` (b `pseq` (a + b)) ?
4 Réponses :
re (1): re (2): Il s'agit d'un calcul assez trivial étant fourchu à d'autres threads; C'est probablement aussi vite que la CPU ne le calculait pas. Je parie que les frais généraux des threads me font mal autant que l'aide de ce calcul simple. P> par code> permet
a code> à calculer dans un autre fil. Je devine ici, mais je pense que
pseq code> se comporte beaucoup comme un
SEQ code>: que cela force le premier résultat d'être calculé en premier (bien,
SEQ code> n'est pas garanti de le faire, mais dans la pratique sur GHC, ça fait). Donc, dans ce cas, le calcul de
A code> est utilisé comme un thread, et l'autre thread calcule
B code>, puis somme
A code> et
B code>. p>
Vous créez un nombre exponentiel d'étincelles (pensez au nombre d'appels récursifs que vous créez ici). Pour réellement obtenir un bon parallélisme, vous devez créer moins em> travail parallèle dans ce cas, car votre matériel ne peut pas gérer que de nombreux threads (et donc GHC ne les font pas). P>
La solution consiste à utiliser une stratégie de coupure, comme décrit dans ce discours: http://donsbot.wordpress.com/2009/09/05/defun-2009-Multicore-programming-in-haskell-now/ P>
Fondamentalement, passez à la version droite à la ligne droite une fois que vous atteignez une certaine profondeur et utilisez + RTS -SSTERR pour voir combien d'étincelles sont converties, vous pouvez donc déterminer si vous gaspillez ou non. P >
Haskell ne balance pas automatiquement des étincelles pour obtenir la meilleure performance?
Il équilibre automatiquement les threads. Le temps d'exécution a des files d'attente d'expressions inévaluées (étincelles) qu'elle convertira des fils à mesure que les charges de travail diminuent. Il vous tient toujours à vous de ne pas créer trop d'étincelles (et donc de perdre du temps à remplir des files d'attente d'étincelles)
comme don a expliqué , le problème est que vous créent trop d'étincelles. Voici comment vous pourriez le réécrire pour obtenir une bonne vitesse. Démonstration: P> [computer ~]$ ghc --make -threaded -O2 Main.hs
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
[computer ~]$ time ./Main +RTS -N1
102334155
real 0m1.509s
user 0m1.450s
sys 0m0.003s
[computer ~]$ time ./Main +RTS -N2
102334155
real 0m0.776s
user 0m1.487s
sys 0m0.023s
[computer ~]$ time ./Main +RTS -N3
102334155
real 0m0.564s
user 0m1.487s
sys 0m0.030s
[computer ~]$ time ./Main +RTS -N4
102334155
real 0m0.510s
user 0m1.587s
sys 0m0.047s
[computer ~]$
Puisque personne n'a donné une réponse définitive sur sémantiquement identique à SEQ, mais
avec une différence opérationnelle subtile:
SEQ est strict dans ses deux arguments,
Donc, le compilateur peut, par exemple,
réorganiser un C'est pourquoi nous avons PSEQ. En revanche
à SEQ, PSEQ n'est que strict dans sa
premier argument (autant que le compilateur
est concerné), qui restreint la
transformations que le compilateur peut
faire et garantit que l'utilisateur peut
Conserver le contrôle de l'évaluation
ordre. p>
blockQuote> PSEQ code>, voici le Description officielle : P>
SEQ code> B dans B
SEQ code> A
SEQ code> b. Ce n'est normalement aucun problème
Lorsque vous utilisez SEQ pour exprimer la striction,
Mais cela peut être un problème quand
annotant le code de parallélisme,
parce que nous avons besoin de plus de contrôle sur le
ordre d'évaluation; Nous pouvons vouloir
évaluer A avant B, parce que nous savons
que b a déjà été déclenché dans
Parallèle avec Par. P>