7
votes

En utilisant parallèle imbriqué.

considérer cet exemple: xxx

Lorsque vous imprimez x nous toujours obtenez 4950. Qu'en est-il si je veux paralliser cela?

Ceci est ce que je propose avec xxx

cependant cela n'imprime pas 4950 chaque fois que je l'exécute. Pourquoi?


5 commentaires

@onof, comment feriez-vous cela?


Parallèle.for (0, 100, i => parallèle.for (i + 1, 100, a => {verrouillage (x) {x + = 1;}}));


Mais verrouillant 'X', vaincre le but d'au moins la boucle intérieure "parallèle".


@onof X est un type de valeur dans cet exemple. Le verrouillage ne peut être utilisé que avec des types de référence.


@chibacité Droit. Il doit s'enrouler


3 Réponses :


15
votes

Des extensions parallèles vous aide à créer une création de tâches, d'allocation, de fonctionnement et de rendez-vous, dans une syntaxe presque impérative. Ce qu'il ne ne prend pas soin de chaque type de sécurité du fil (l'un des pièges ). Vous essayez de faire des threads parallèles simultanément mettre à jour une seule variable partagée. Pour faire quelque chose comme ça correctement, vous devez introduire E.G. verrouillage.

Je ne suis pas sûr de ce que vous essayez de faire. Je suppose que votre code n'est qu'un espace réservé ou une expérience. La parallélisation ne convient que lorsque vous pouvez isoler vos différentes pièces de travail; Pas lorsque vous devez constamment vous rendre avec des données partagées.


2 commentaires

Les données que j'ai sont uniquement lues, il y a une seule variable (collection) que j'ajoute des résultats et je m'en soucie de l'ordre à qui elles ont été ajoutées ici. Verrouille un mécanicon lent?


Le verrouillage extrême peut vous donner pire performance que la simple implémentation séquentielle. Pensez à utiliser par exemple. Parallel.Accrégation () Pour combiner vos résultats à la place. Regardez par ex. msdn.microsoft.com/en-us/magazine/cc163340.aspx.



0
votes

Autre alternative au verrouillage à chaque fois, vous pouvez utiliser des variables de thread-local en combinaison avec un verrou:

Object thisLock = new Object();
var globalSum = 0;
System.Threading.Tasks.Parallel.For(0, 100, i => {
    System.Threading.Tasks.Parallel.For(i + 1, 100, () => 0, (num, loopState, subSum) => ++subSum, subSum => { 
        lock(thisLock) { globalSum += subSum; }
    });
});

Console.WriteLine(globalSum);


1 commentaires

@Mattsmith Ouais désolé, il a un peu foiré lors de la copie de Visual Studio :)



2
votes

Voici la méthode "correcte" de le faire, cela ne vous obligerait pas à verrouiller votre objet total final et ne vous demanderait que de faire les opérations verrouillées à la fin de la boucle de chaque fil local.

int x = 0;
Parallel.For(0, 100,
    () => 0, //LocalInit
    (i, loopstate, outerlocal) =>
    {
        Parallel.For(i + 1, 100,
            () => 0, //LocalInit
            (a, loopState, innerLocal) => { return innerLocal + 1; },
            (innerLocal) => Interlocked.Add(ref outerlocal, innerLocal)); //Local Final
        return outerlocal;
    },
    (outerLocal) => Interlocked.Add(ref x, outerLocal)); //Local Final


0 commentaires