Bagikan melalui


Cara: Mempercepat Isi Perulangan Kecil

Ketika perulangan Parallel.For memiliki tubuh kecil, perulangan mungkin berkinerja lebih lambat daripada perulangan berurutan yang setara, seperti untuk perulangan di C# dan untuk perulangan di Visual Basic. Kinerja yang lebih lambat disebabkan oleh overhead yang terlibat dalam partisi data dan biaya untuk memanggil delegasi pada setiap loop. Untuk mengatasi skenario tersebut, kelas Partitioner menyediakan metodePartitioner.Create, yang memungkinkan Anda untuk memberikan perulangan berurutan untuk isi delegasi, sehingga delegasi hanya dipanggil sekali per partisi, bukan sekali per iterasi. Untuk informasi selengkapnya, lihat Partisi Kustom untuk PLINQ dan TPL.

Contoh

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

Pendekatan yang ditunjukkan dalam contoh ini berguna ketika perulangan melakukan pekerjaan dalam jumlah kecil. Karena pekerjaan menjadi lebih mahal secara komputasi, Anda mungkin akan mendapatkan performa yang sama atau lebih baik dengan menggunakan perulangan For atau ForEach dengan partisi default tersebut.

Lihat juga