Parallel Language Integrated Query (PLINQ)

publicitemcppreparation

 

Attention : Pour mieux comprendre cet article, des connaissances en LINQ sont nécessaires 

 Présentation

 Parallel Language Integrated Query (PLINQ) est une implémentation parallèle de LINQ (Language Integrated Query) présente dans le .NET Framework depuis la version 4.0. Son objectif est  d’utiliser au maximum tous les processeurs du système (ou ceux que l’on souhaite, il y a la possibilité de limiter le nombre de processeurs utilisés via la méthode WithDegreeOfParallelism) pour améliorer les performances d’exécution des requêtes. Les requêtes PLINQ s’exécutent sur toute collection d’objets héritant de l’interface IEnumerable<T> . Avec PLINQ, les itérations sont exécutées en parallèle comme des Tasks.

Toutes les méthodes d’extensions de PLINQ (Where, Select, OrderBy, Skip…) sont présentent dans l’espace de nom System.Linq.ParallelEnumerable.

L’un des avantages du PLINQ est qu’il est très simple à utiliser. Eh oui!…convertir une requête LINQ en PLINQ est un jeu d’enfant :).

Pour exécuter une requête PLINQ, il faut faire appel à la méthode d’extension AsParallel() dans la requête LINQ. Elle permet d’activer la parallélisation de la requête.

Exemple :  

            String Name = « PLINQ »;

            var MyPlinqQuery= from subject in subjects.AsParallel()

                              where subject.Name == Name

                              orderby subject.Name

                              select subject;

Les opérateurs et Méthodes d’extensions

Pour améliorer les performances de son utilisation, PLINQ contient un ensemble d’opérateurs et de méthodes d’extensions.

Cette section a comme objectif de vous présenter une partie de ces éléments.

  1. L’opérateur ForAll

 Les requêtes PLINQ renvoient une source de données de type IEnumerable ou IEnumerable<T>. Pour exploiter les données renvoyées, une itération est nécessaire. Or, comme nous sommes sur un traitement en parallèle, l’itération doit l’être également pour conserver le parallélisme.

Contrairement à ForEach qui lui est séquentiel, ForAll n’a pas besoin d’attendre que toutes les données renvoyées par la requête PLINQ soient récupérées.

Ce qui veut dire que dans le cas où une requête PLINQ renvoie au total 50 items, ForAll ne va pas attendre que tous les items soient récupérés avant d’agir. Mais plutôt, dès la réception du premier item. Et par conséquent, la notion de traitement en parallèle est conservée.

 Exemple :

             String Name = « PLINQ »;

            var MyPlinqQuery= from subject in subjects.AsParallel()

                              where subject.Name == Name

                              orderby subject.Name

                              select subject;

            MyPlinqQuery.ForAll((item) => Console.WriteLine(item));

  1. AsOrdered()

 L’un des inconvénients du PLINQ, c’est qu’il n’existe aucun ordonnancement par défaut. Pour ordonner le résultat des requêtes, il faut utiliser la méthode d’extension AsOrdered().

 Exemple :

             String Name = « PLINQ »;

            var MyPlinqQuery= from subject in subjects.AsParallel().AsOrdered()

                              where subject.Name == Name

                              orderby subject.Name

                              select subject;

  1. WithDegreeOfParallelism ()

Par défaut, PLINQ utilise tous les cores du processeur (jusqu’au maximum de 64). Vous pouvez gérer la quantité de cores à utiliser lors de l’exécution de la requête PLINQ en utilisant WithDegreeOfParallelism().

  1. AsSequential ()

Il arrive parfois qu’une partie de la requête PLINQ doit s’exécuter en séquentiel. AsSequential() permet d’arrêter l’exécution en parallèle d’une partie de la requête.

  1. ParallelExecutionMode

Bien que la méthode AsParallel() convertit une requête LINQ en PLINQ, l’exécution en parallèle de celle-ci n’est pas garantie.

Evaluer les gains en performances d’une requête PLINQ est une science inexacte basée sur plusieurs facteurs à savoir :

  • La longueur des opérations.
  • Le nombre de cores dans le processeur.
  • Le type de résultat renvoyé.
  • Les options de merge.

Durant son exécution, une requête PLINQ permet de choisir entre une exécution en parallèle ou séquentielle. Elle ne prend pas en compte tous les facteurs cités ci-dessus.

L’énumération ParallelExecutionMode spécifie comment le système doit gérer des échanges de performances lorsque les requêtes PLINQ sont exécutées.

Elle contient deux valeurs :

  • Default: Si la structure de la requête indique qu’aucune accélération de l’exécution ne sera probablement obtenue, PLINQ exécute la requête comme une requête LINQ to Objects ordinaire.
  • ForceParallelism : Force l’utilisation de l’exécution de la requête en parallèle dans tous les cas.

Conclusion

 L’objectif de PLINQ consiste à accélérer l’exécution des requêtes LINQ to Objects en exécutant les délégués de requête en parallèle sur les ordinateurs multicœurs.

PLINQ possède plusieurs méthodes d’extensions, opérateurs, énumérations…qui permettent d’améliorer les performances d’exécutions mais aussi pour faciliter l’écriture des requêtes PLINQ.

L’utilisation du PLINQ à la place du LINQ ne garantit pas une exécution plus rapide du programme.

PLINQ est utile pour les requêtes nécessitant une grande quantité de calcul.

Les itérations ForEach, For et ForAll ne s’exécutent pas forcément toujours en parallèle.

Lors d’une exécution en parallèle, il peut avoir des opérations qui génèrent des exceptions. Elles sont gérées par le .NET Framework sous forme d’AggregateException.