Aracılığıyla paylaş


Nasıl yapılır: Küçük Döngü Gövdelerini Hızlandırma

Döngü Parallel.For küçük bir gövdeye sahip olduğunda, C# içindeki for döngüsü ve Visual Basic'teki For döngüsü gibi eşdeğer sıralı döngüden daha yavaş çalışabilir. Performansın yavaş olması, verilerin bölümlenmesine neden olan ek yük ve her döngü yinelemesinde bir temsilci çağırma maliyetinden kaynaklanır. Bu tür senaryoları ele almak için sınıfı, Partitioner temsilci gövdesi için sıralı bir döngü sağlamanıza olanak tanıyan yöntemini sağlar Partitioner.Create , böylece temsilci yineleme başına bir kez yerine bölüm başına yalnızca bir kez çağrılır. Daha fazla bilgi için bkz . PLINQ ve TPL için Özel Bölümleyiciler.

Örnek

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static void Main()
    {

        // Source must be array or IList.
        var source = Enumerable.Range(0, 100000).ToArray();

        // Partition the entire source array.
        var rangePartitioner = Partitioner.Create(0, source.Length);

        double[] results = new double[source.Length];

        // Loop over the partitions in parallel.
        Parallel.ForEach(rangePartitioner, (range, loopState) =>
        {
            // Loop over each range element without a delegate invocation.
            for (int i = range.Item1; i < range.Item2; i++)
            {
                results[i] = source[i] * Math.PI;
            }
        });

        Console.WriteLine("Operation complete. Print results? y/n");
        char input = Console.ReadKey().KeyChar;
        if (input == 'y' || input == 'Y')
        {
            foreach(double d in results)
            {
                Console.Write("{0} ", d);
            }
        }
    }
}
Imports System.Threading.Tasks
Imports System.Collections.Concurrent

Module PartitionDemo

    Sub Main()
        ' Source must be array or IList.
        Dim source = Enumerable.Range(0, 100000).ToArray()

        ' Partition the entire source array. 
        ' Let the partitioner size the ranges.
        Dim rangePartitioner = Partitioner.Create(0, source.Length)

        Dim results(source.Length - 1) As Double

        ' Loop over the partitions in parallel. The Sub is invoked
        ' once per partition.
        Parallel.ForEach(rangePartitioner, Sub(range, loopState)

                                               ' Loop over each range element without a delegate invocation.
                                               For i As Integer = range.Item1 To range.Item2 - 1
                                                   results(i) = source(i) * Math.PI
                                               Next
                                           End Sub)
        Console.WriteLine("Operation complete. Print results? y/n")
        Dim input As Char = Console.ReadKey().KeyChar
        If input = "y"c Or input = "Y"c Then
            For Each d As Double In results
                Console.Write("{0} ", d)
            Next
        End If

    End Sub
End Module

Bu örnekte belirtilen yaklaşım, döngü en az miktarda iş gerçekleştirdiğinde yararlıdır. çalışma işlem açısından daha pahalı hale geldikçe, varsayılan bölümleyici ile bir For veya döngüsü kullanarak büyük olasılıkla aynı veya ForEach daha iyi performans elde edersiniz.

Ayrıca bkz.