Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Artikel ini memperlihatkan cara menggunakan perulangan Parallel.ForEach untuk mengaktifkan paralelisme data atas sumber data atau System.Collections.Generic.IEnumerable<T> apa punSystem.Collections.IEnumerable.
Catatan
Dokumentasi ini menggunakan ekspresi lambda untuk menentukan delegasi di PLINQ. Jika Anda tidak terbiasa dengan ekspresi lambda di C# atau Visual Basic, lihat Ekspresi Lambda di PLINQ dan TPL.
Contoh
Contoh ini menunjukkan Parallel.ForEach operasi intensif CPU. Saat Anda menjalankan contoh, contoh tersebut secara acak menghasilkan 2 juta angka dan mencoba memfilter ke angka utama. Kasus pertama mengulangi koleksi melalui perulangan for. Kasus kedua melakukan iterasi atas koleksi melalui Parallel.ForEach. Waktu proses yang dibutuhkan oleh setiap pengulangan ditampilkan ketika aplikasi selesai.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace ParallelExample
{
class Program
{
static void Main()
{
// 2 million
var limit = 2_000_000;
var numbers = Enumerable.Range(0, limit).ToList();
var watch = Stopwatch.StartNew();
var primeNumbersFromForeach = GetPrimeList(numbers);
watch.Stop();
var watchForParallel = Stopwatch.StartNew();
var primeNumbersFromParallelForeach = GetPrimeListWithParallel(numbers);
watchForParallel.Stop();
Console.WriteLine($"Classical foreach loop | Total prime numbers : {primeNumbersFromForeach.Count} | Time Taken : {watch.ElapsedMilliseconds} ms.");
Console.WriteLine($"Parallel.ForEach loop | Total prime numbers : {primeNumbersFromParallelForeach.Count} | Time Taken : {watchForParallel.ElapsedMilliseconds} ms.");
Console.WriteLine("Press 'Enter' to exit.");
Console.ReadLine();
}
/// <summary>
/// GetPrimeList returns Prime numbers by using sequential ForEach
/// </summary>
/// <param name="inputs"></param>
/// <returns></returns>
private static IList<int> GetPrimeList(IList<int> numbers) => numbers.Where(IsPrime).ToList();
/// <summary>
/// GetPrimeListWithParallel returns Prime numbers by using Parallel.ForEach
/// </summary>
/// <param name="numbers"></param>
/// <returns></returns>
private static IList<int> GetPrimeListWithParallel(IList<int> numbers)
{
var primeNumbers = new ConcurrentBag<int>();
Parallel.ForEach(numbers, number =>
{
if (IsPrime(number))
{
primeNumbers.Add(number);
}
});
return primeNumbers.ToList();
}
/// <summary>
/// IsPrime returns true if number is Prime, else false.(https://en.wikipedia.org/wiki/Prime_number)
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
private static bool IsPrime(int number)
{
if (number < 2)
{
return false;
}
for (var divisor = 2; divisor <= Math.Sqrt(number); divisor++)
{
if (number % divisor == 0)
{
return false;
}
}
return true;
}
}
}
Imports System.Collections.Concurrent
Namespace ParallelExample
Class Program
Shared Sub Main()
' 2 million
Dim limit = 2_000_000
Dim numbers = Enumerable.Range(0, limit).ToList()
Dim watch = Stopwatch.StartNew()
Dim primeNumbersFromForeach = GetPrimeList(numbers)
watch.Stop()
Dim watchForParallel = Stopwatch.StartNew()
Dim primeNumbersFromParallelForeach = GetPrimeListWithParallel(numbers)
watchForParallel.Stop()
Console.WriteLine($"Classical foreach loop | Total prime numbers : {primeNumbersFromForeach.Count} | Time Taken : {watch.ElapsedMilliseconds} ms.")
Console.WriteLine($"Parallel.ForEach loop | Total prime numbers : {primeNumbersFromParallelForeach.Count} | Time Taken : {watchForParallel.ElapsedMilliseconds} ms.")
Console.WriteLine("Press 'Enter' to exit.")
Console.ReadLine()
End Sub
' GetPrimeList returns Prime numbers by using sequential ForEach
Private Shared Function GetPrimeList(numbers As IList(Of Integer)) As IList(Of Integer)
Return numbers.Where(AddressOf IsPrime).ToList()
End Function
' GetPrimeListWithParallel returns Prime numbers by using Parallel.ForEach
Private Shared Function GetPrimeListWithParallel(numbers As IList(Of Integer)) As IList(Of Integer)
Dim primeNumbers = New ConcurrentBag(Of Integer)()
Parallel.ForEach(numbers, Sub(number)
If IsPrime(number) Then
primeNumbers.Add(number)
End If
End Sub)
Return primeNumbers.ToList()
End Function
' IsPrime returns true if number is Prime, else false.(https://en.wikipedia.org/wiki/Prime_number)
Private Shared Function IsPrime(number As Integer) As Boolean
If number < 2 Then
Return False
End If
For divisor = 2 To Math.Sqrt(number)
If number Mod divisor = 0 Then
Return False
End If
Next
Return True
End Function
End Class
End Namespace
Pengulangan Parallel.ForEach bekerja seperti pengulangan Parallel.For. Pengulangan mempartisi kumpulan sumber dan menjadwalkan pekerjaan pada beberapa utas berdasarkan lingkungan sistem. Semakin banyak prosesor pada sistem, semakin cepat metode paralel berjalan. Untuk beberapa koleksi sumber, perulangan berurutan mungkin lebih cepat, tergantung pada ukuran sumber dan jenis pekerjaan yang dilakukan perulangan. Untuk informasi selengkapnya tentang performa, lihat Potensi perangkap dalam paralelisme data dan tugas.
Untuk informasi selengkapnya tentang pengulangan paralel, lihat Cara: Menulis pengulangan sederhana Paralel.For.
Untuk menggunakan perulangan Parallel.ForEach dengan koleksi non-generik, Anda dapat menggunakan Enumerable.Cast metode ekstensi untuk mengonversi koleksi ke koleksi generik, seperti yang ditunjukkan dalam contoh berikut:
Parallel.ForEach(nonGenericCollection.Cast<object>(),
currentElement =>
{
});
Parallel.ForEach(nonGenericCollection.Cast(Of Object), _
Sub(currentElement)
' ... work with currentElement
End Sub)
Anda juga dapat menggunakan Parallel LINQ (PLINQ) untuk menyejajarkan pemrosesan IEnumerable<T> sumber data. PLINQ memungkinkan Anda menggunakan sintaks kueri deklaratif untuk mennyatakan perilaku pengulangan. Untuk informasi selengkapnya, lihat LINQ Paralel (PLINQ).
Kompilasi dan jalankan kode tersebut
Anda dapat mengompilasi kode sebagai aplikasi konsol untuk .NET Framework atau sebagai aplikasi konsol untuk .NET Core.
Di Visual Studio, ada templat aplikasi konsol Visual Basic dan C# untuk Windows Desktop dan .NET Core.
Dari baris perintah, Anda dapat menggunakan perintah .NET CLI (misalnya, dotnet new console atau dotnet new console -lang vb) atau membuat file dan menggunakan compiler baris perintah untuk aplikasi .NET Framework.
Untuk menjalankan aplikasi konsol .NET Core dari baris perintah, gunakan dotnet run dari folder yang berisi aplikasi Anda.
Untuk menjalankan aplikasi konsol dari Visual Studio, tekan F5.