Options de fusion en PLINQMerge Options in PLINQ

Quand une requête s’exécute en parallèle, PLINQ partitionne la séquence source pour que plusieurs threads puissent fonctionner simultanément sur différentes parties, généralement sur des threads distincts.When a query is executing as parallel, PLINQ partitions the source sequence so that multiple threads can work on different parts concurrently, typically on separate threads. Si les résultats doivent être utilisés sur un thread, par exemple, dans une boucle foreach (For Each en Visual Basic), les résultats de chaque thread doivent être fusionnés de nouveau en une séquence.If the results are to be consumed on one thread, for example, in a foreach (For Each in Visual Basic) loop, then the results from every thread must be merged back into one sequence. Le type de fusion que PLINQ exécute dépend des opérateurs présents dans la requête.The kind of merge that PLINQ performs depends on the operators that are present in the query. Par exemple, les opérateurs qui imposent un nouvel ordre des résultats doivent mettre en mémoire tampon tous les éléments de tous les threads.For example, operators that impose a new order on the results must buffer all elements from all threads. Du point de vue du thread utilisateur (qui est également celui de l’utilisateur de l’application), une requête entièrement mise en mémoire tampon peut s’exécuter pendant un certain temps avant qu’elle ne génère son premier résultat.From the perspective of the consuming thread (which is also that of the application user) a fully buffered query might run for a noticeable period of time before it produces its first result. D’autres opérateurs, par défaut, sont partiellement mis en mémoire tampon. Ils transmettent leurs résultats par lots.Other operators, by default, are partially buffered; they yield their results in batches. L’opérateur ForAll n’est pas mis en mémoire tampon par défaut.One operator, ForAll is not buffered by default. Il transmet immédiatement tous les éléments à partir de tous les threads.It yields all elements from all threads immediately.

À l’aide de la méthode WithMergeOptions, comme indiqué dans l’exemple suivant, vous pouvez fournir un indicateur à PLINQ spécifiant le type de fusion à exécuter.By using the WithMergeOptions method, as shown in the following example, you can provide a hint to PLINQ that indicates what kind of merging to perform.

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                Where n Mod 2 = 0
                Select ExpensiveFunc(n)

Pour obtenir un exemple complet, consultez Comment : spécifier des options de fusion en PLINQ.For the complete example, see How to: Specify Merge Options in PLINQ.

Si la requête ne peut pas prendre en charge l’option demandée, cette dernière sera simplement ignorée.If the particular query cannot support the requested option, then the option will just be ignored. Dans la plupart des cas, il n’est pas nécessaire de spécifier une option de fusion pour une requête PLINQ.In most cases, you do not have to specify a merge option for a PLINQ query. Toutefois, dans certains cas, après avoir effectué des tests et des mesures, vous pouvez trouver qu’une requête s’exécute mieux dans un mode non défini par défaut.However, in some cases you may find by testing and measurement that a query executes best in a non-default mode. Cette option est souvent utilisée pour forcer un opérateur de fusion de blocs à diffuser ses résultats en continu afin de fournir une interface utilisateur plus réactive.A common use of this option is to force a chunk-merging operator to stream its results in order to provide a more responsive user interface.

ParallelMergeOptionsParallelMergeOptions

L’énumération ParallelMergeOptions inclut les options suivantes qui spécifient, pour les formes de requête prises en charge, la manière dont la sortie finale de la requête est transmise quand les résultats sont utilisés sur un thread :The ParallelMergeOptions enumeration includes the following options that specify, for supported query shapes, how the final output of the query is yielded when the results are consumed on one thread:

  • Not Buffered

    Avec l’option NotBuffered, chaque élément traité est retourné à partir de chaque thread dès qu’il est généré.The NotBuffered option causes each processed element to be returned from each thread as soon as it is produced. Ce comportement revient à « diffuser en continu » la sortie.This behavior is analogous to "streaming" the output. Si l’opérateur AsOrdered est présent dans la requête, NotBuffered conserve l’ordre des éléments sources.If the AsOrdered operator is present in the query, NotBuffered preserves the order of the source elements. Bien que NotBuffered commence à produire des résultats dès qu’ils sont disponibles, la durée totale de production de tous les résultats peut toujours être plus longue que l’utilisation de l’une des autres options de fusion.Although NotBuffered starts yielding results as soon as they're available, the total time to produce all the results might still be longer than using one of the other merge options.

  • Auto Buffered

    Avec l’option AutoBuffered, la requête regroupe des éléments dans une mémoire tampon, puis transmet régulièrement tout le contenu de cette mémoire simultanément au thread utilisateur.The AutoBuffered option causes the query to collect elements into a buffer and then periodically yield the buffer contents all at once to the consuming thread. Cette option revient à transmettre les données sources dans des « blocs » au lieu d’utiliser le comportement de « diffusion en continu » de NotBuffered.This is analogous to yielding the source data in "chunks" instead of using the "streaming" behavior of NotBuffered. AutoBuffered peut nécessiter plus de temps que NotBuffered pour rendre le premier élément disponible sur le thread utilisateur.AutoBuffered may take longer than NotBuffered to make the first element available on the consuming thread. La taille de la mémoire tampon et le comportement exact de transmission ne sont pas configurables et peuvent varier en fonction de différents facteurs liés à la requête.The size of the buffer and the exact yielding behavior are not configurable and may vary, depending on various factors that relate to the query.

  • FullyBuffered

    Avec l’option FullyBuffered, la sortie de la requête entière est mise en mémoire tampon avant que l’un des éléments ne soit transmis.The FullyBuffered option causes the output of the whole query to be buffered before any of the elements are yielded. Cette option peut nécessiter plus de temps pour que le premier élément soit disponible sur le thread utilisateur, mais les résultats complets peuvent toujours être générés plus rapidement qu’avec les autres options.When you use this option, it can take longer before the first element is available on the consuming thread, but the complete results might still be produced faster than by using the other options.

Opérateurs de requête prenant en charge les options de fusionQuery Operators that Support Merge Options

Le tableau suivant répertorie les opérateurs qui prennent en charge tous les modes d’options de fusion, qui sont soumis aux restrictions spécifiées.The following table lists the operators that support all merge option modes, subject to the specified restrictions.

OpérateurOperator RestrictionsRestrictions
AsEnumerable NoneNone
Cast NoneNone
Concat Requêtes non ordonnées qui ont uniquement une source de type Tableau ou Liste.Non-ordered queries that have an Array or List source only.
DefaultIfEmpty NoneNone
OfType NoneNone
Reverse Requêtes non ordonnées qui ont uniquement une source de type Tableau ou Liste.Non-ordered queries that have an Array or List source only.
Select NoneNone
SelectMany NoneNone
Skip NoneNone
Take NoneNone
Where NoneNone

Tous les autres opérateurs de requête PLINQ peuvent ignorer les options de fusion fournis par l’utilisateur.All other PLINQ query operators might ignore user-provided merge options. Certains opérateurs de requête, tels que Reverse et OrderBy, ne peuvent pas transmettre d’éléments tant qu’ils n’ont pas tous été générés et réorganisés.Some query operators, for example, Reverse and OrderBy, cannot yield any elements until all have been produced and reordered. Par conséquent, si vous utilisez ParallelMergeOptions dans une requête qui contient également un opérateur tel que Reverse, le comportement de fusion ne sera appliqué dans la requête qu’une fois que l’opérateur aura généré ses résultats.Therefore, when ParallelMergeOptions is used in a query that also contains an operator such as Reverse, the merge behavior will not be applied in the query until after that operator has produced its results.

La capacité de certains opérateurs à gérer les options de fusion varie selon le type de la séquence source et selon que l’opérateur AsOrdered a été utilisé antérieurement dans la requête ou non.The ability of some operators to handle merge options depends on the type of the source sequence, and whether the AsOrdered operator was used earlier in the query. ForAll est toujours NotBuffered ; il transmet immédiatement ses éléments.ForAll is always NotBuffered ; it yields its elements immediately. OrderBy est toujours FullyBuffered ; il doit trier l’intégralité de la liste avant toute transmission.OrderBy is always FullyBuffered; it must sort the whole list before it yields.

Voir aussiSee also