6
votes

Changer la valeur incrémentielle d'un C # parallel.for boucle

Je veux convertir A pour boucle qui incristent l'itérateur par 2 chaque passe en parallèle pour la boucle à l'aide du TPL. Les données ne sont ni commandes dépendantes ou contraintes de quelque manière que ce soit, mais je veux seulement traiter les données dans tous les autres éléments de mon ensemble source (qui est _Dataliste dans le code ci-dessous), d'où la nécessité d'augmenter par 2.

My Pour boucle: xxx

est-il possible de dire à la boucle parallèle que je veux incrémenter i par deux au lieu d'un?

Voici la boucle parallèle, mais évidemment, je ne s'agit que d'incrémenter par 1 chaque itération: xxx

Je pourrais dire au corps de la boucle interne d'ignorer les valeurs impaires de I, mais qui semble un limiteur désordonné - y a-t-il un façon de le faire dans l'initialisation de la boucle en quelque sorte?


2 commentaires

Ne pas ignorer les valeurs étranges; Cela crée deux fois plus de tâches que vous en avez besoin, ce qui ajoute beaucoup de frais généraux inutiles.


Oui, je vois ce que tu veux dire


4 Réponses :


12
votes

Vous pouvez réduire de moitié le nombre d'étapes et doubler les indices:

Parallel.For(0, _DataList.Length / 2, i =>
{
    // do work for _DataList[2 * i]                    
});


0 commentaires

11
votes

Que diriez-vous:

var odds = Enumerable.Range(1, _DataList.Length).Where(i => i % 2 != 0);

Task.Factory.StartNew(() =>
    Parallel.ForEach(odds, i =>
    {
        // do work for _DataList[i]                    
    })
);


0 commentaires

1
votes

La réponse de Darin Dimitrov montre un moyen facile d'accomplir cela.

Cependant, cela n'a pas été ajouté, car il s'agit généralement d'un signe que les corps en boucle ne sont pas vraiment distincts. Dans la plupart des cas, la nécessité d'utiliser une valeur d'augmentation différente n'est généralement liée que la nécessité de traiter dans un ordre spécifique ou d'autres préoccupations qui entraîneront la parallélisation pour créer des conditions de course.


3 commentaires

Noté pour référence future, mais dans le cas où je postule cette boucle, l'ordre de traitement des éléments n'est vraiment pas une préoccupation


@Gareth: Je viens de mentionner cela puisqu'il y avait une discussion (que je ne trouve pas ATM) par Stephen Toub mentionnant spécifiquement pourquoi parallèle. Traitement, mais vous pouvez toujours travailler autour d'elle via un partitionnaire ou parallèle.


Je crois que cet étui d'utilisation se présente très naturellement lorsque vous travaillez avec des instructions de SIMD dans .NET, car ils fonctionnent en créant un vecteur <'T> pour chaque nième élément d'un tableau, où n est la largeur de le vecteur. Vous ne pouvez pas tirer parti de parallèle.Pour pour de petites fonctions vectorisées, car les astuces d'énumérateur ou de multiplication ont vaincu la prestation PERF.



0
votes

Sautez juste des valeurs même. XXX


2 commentaires

Pouvez-vous expliquer plus sur votre réponse? Il est généralement considéré comme une bonne pratique pour donner des informations ou des explications pour les réponses que vous donnez. Cela peut aider les futurs utilisateurs ou op plus.


Ce n'est pas une bonne idée que vous créez des frais généraux et c'est ce que j'essayais d'éviter - voir le premier commentaire sur la question. Heureusement, il y a quelques bonnes solutions il y a 5 ans :)