En parallèle.Pour(): mise à Jour de la variable en dehors de la boucle
Je suis juste à la recherche de la nouvelle .NET 4.0 caractéristiques. Cela dit, je vais tenter de faire un simple calcul à l'aide de Parallel.For
et de normal for(x;x;x)
boucle.
Cependant, j'obtiens des résultats différents à environ 50% du temps.
long sum = 0;
Parallel.For(1, 10000, y =>
{
sum += y;
}
);
Console.WriteLine(sum.ToString());
sum = 0;
for (int y = 1; y < 10000; y++)
{
sum += y;
}
Console.WriteLine(sum.ToString());
Ma conjecture est que les fils sont en train de mettre à jour "somme" en même temps.
Est-il une façon évidente autour d'elle?
- La programmation simultanée est livré en deux parties, 1) l'exécution d'un thread séparé, et 2) la synchronisation\la communication entre les threads. parallel extensions permettent 1), cependant 2) doit être traitée explicitement par le développeur, et quand vous dites
sum += y;
vous sont effectivement avoir chaque thread dire "m'ajouter à la somme!", tout à la fois. vous avez besoin de synchroniser leur communication en ce qui concerne la ressource partagéesum
- mes craintes se réalisent... parallel extensions de laisser les gens à écrire du code en parallèle sans la compréhension de la théorie, y compris les conditions de course (comme ici)
- Oui, c'est pourquoi certains d'entre nous vraiment essayer de l'apprendre en premier (c'est à dire. en affichant des questions sur soi).
- je vous recommande de lire quelques articles sur le multithreading et essayer de le programmer dans le niveau inférieur, à l'aide de threads. puis passer à extensions parallèles, parce que c'est juste un wrapper et il cache beaucoup de choses de vous.
- Je ne sais pas pourquoi Msft introduit en parallèle des extensions de la première place... il va juste pour encourager les gens à parallèle des trucs qui ne devraient pas/n'a pas besoin d'être exécutées en parallèle.
- Je ne pense pas que vous avez beaucoup à apprendre de faible niveau de programmation de threads, mais vous avez à comprendre les enjeux. Le TPL fait beaucoup pour aider à la création et à la gestion des threads par abstraction comme un type de Tâche. Il ne fait pas beaucoup pour aider avec des données partagées. Vous devez comprendre ces questions, même lors de l'utilisation de tâches.
- Même avec LINQ, ne sais pas pourquoi MS introduit que ce soit. Nous avons de la boucle! /sarcasme
- Je n'ai fait aucune référence à LINQ... Ce que je fais remarquer, c'est que les frais généraux de quelque chose comme ceci est beaucoup plus élevé que l'exécution de cette tout dans un seul thread. Les gens vont commencer à lancer en Parallèle.Pour n'importe quel endroit dans le code de leurs ils ont de grandes boucles... ce que je veux dire c'est que cela va encourager les gens à introduire inutilement le multithreading dans leurs programmes.
- Parce qu'il y est un changement fondamental dans la plate-forme matérielle. Je vous suggère de regarder le Manycore Maj du papier blanc, et microsoft.com/downloads/... Herb Sutter la Fin de la Déjeuner gratuit, l'article gotw.ca/publications/concurrency-ddj.htm
- droit, mais combien de fois allez-vous écrire une vraie boucle qui est suffisamment long pour justifier le multithreading?? Même avec plusieurs cœurs, le multithreading, qui fonctionne le mieux avec IO lié ou très fortement dépendant du PROCESSEUR des tâches... et sans surprise, la plupart de code n'est PAS très IO ou liées à l'UC. Mon point est que cela va encourager n00bies de jeter le multithreading à chaque problème.
- juste pickin', et ce n'était qu'un exemple trivial. @AdeMiller: exactement pourquoi je pense que c'est important. Je pourrais sortir avec un couple simple threads dans une application au cours des années, mais maintenant, avec 6 processeurs à cœur, pourquoi ne pas créer plus rapide et évolutive des applications?
- Nous nous dirigeons vers un monde où les ordinateurs ont des centaines de cœurs. Pour ce monde, il est logique de faire des programmes multithread. D'ailleurs, pourquoi détestez-vous sur une technologie qui rend la programmation de quelque chose de difficile beaucoup plus facile?
- mon point n'était pas que cette fonctionnalité n'est pas TOUJOURS inutile, certes, il y aura donc des cas utiles pour cela. Je dis simplement que, dans la PLUPART des CAS, cette fonctionnalité est complètement inutile, et sera effectivement RALENTIR votre code vers le bas. Il n'a pas d'importance combien de flipper coeurs que vous avez, il va y avoir des coûts additionnels dans la fabrication de ces cœurs de communiquer avec d'autres personnes. Donc, il est idéal pour faire ces carottes de parler à d'autres personnes quand ils absolument.
- parallel extensions ne prétends pas obtenir beaucoup plus facile.
- sur les Gpu des centaines de cœurs sont la réalité d'aujourd'hui.
- Je pense que le souci, c'est si les gens écrire du code sans le comprendre, et de se contenter de poser des questions quand le résultat est différent de ce à quoi ils s'attendaient. Le problème avec cette méthode est que vous pouvez écrire du code qui semble bien fonctionner quand vous le tester sur votre single core dev machine sur de petites quantités de données, mais échoue lamentablement lorsque vous déployez pour le multicœur serveur de production et de grands ensembles de données. Toutefois, +1 pour la question.
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas faire cela.
sum
est partagé entre vous threads parallèles. Vous devez vous assurer que lesum
variable est uniquement accessible par un seul thread à la fois:MAIS... C'est un anti-modèle, car vous avez effectivement sérialisés la boucle parce que chaque thread se bloque sur le
Interlocked.Add
.Ce que vous devez faire est d'ajouter des sous-totaux et les fusionner à la fin comme ceci:
Vous pouvez trouver de plus amples discussions sur la MSDN: http://msdn.microsoft.com/en-us/library/dd460703.aspx
PLUG: Vous pouvez trouver plus sur ce sujet dans le Chapitre 2 sur Un Guide pour la Programmation Parallèle
La suivante est aussi certainement en valeur une lecture...
Les modèles de Programmation Parallèle: la Compréhension et l'Application de Modèles Parallèles avec la .NET Framework 4 - Stephen Toub
sum += y;
est en faitsum = sum + y;
. Vous obtenez des résultats erronés en raison de la course suivante condition:sum
sum
sum+y1
, et stocke le résultat danssum
sum+y2
, et stocke le résultat danssum
sum
est maintenant égal àsum+y2
, au lieu desum+y1+y2
.Votre conjecturer est correct.
Lorsque vous écrivez
sum += y
, le moteur d'exécution est le suivant:y
de la pileSi deux threads de lire le champ, dans le même temps, la modification apportée par le premier thread sera remplacé par le deuxième thread.
Vous devez utiliser
Interloqué.Ajouter
, qui effectue l'addition comme une seule opération atomique.Incrémentation d'une longue n'est pas une opération atomique.
Je pense qu'il est important de distinguer que cette boucle n'est pas capable d'être partitionné pour le parallélisme, car comme il a été mentionné ci-dessus chaque itération de la boucle dépend de l'avant. Le parallèle a pour but explicite des tâches parallèles, telles que les pixels de mise à l'échelle, etc. parce que chaque itération de la boucle ne peut pas avoir de dépendances de données en dehors de son itération.
Ci-dessus un exemple de code qui permet de facile de partitionnement pour le parallélisme. Cependant, un mot d'avertissement, le parallélisme est livré avec un prix, même la boucle que j'ai utilisé comme exemple est loin beaucoup trop simple de s'embêter avec un parallèle parce que le temps prend plus de temps que le temps gagné par le parallélisme.
Un point important, nul ne semble avoir mentionné: Pour data-parallèle des opérations (telles que l'OP s), il est souvent mieux (en termes d'efficacité et de simplicité) pour utiliser PLINQ au lieu de la
Parallel
classe. L'OP du code est en fait triviale pour paralléliser:L'extrait ci-dessus utilise le
ParallelEnumerable.Somme
méthode, bien que l'on puisse aussi utiliserAgrégation
pour plus d'scénarios généraux. Reportez-vous à la Boucles Parallèles chapitre pour une explication de ces approches.si il y a deux paramètres dans le présent code.
Par exemple
qu'allons-nous faire ? je suppose que l'utilisation de la matrice de !