Pelestarian Pesanan di PLINQ
Dalam PLINQ, tujuannya adalah untuk memaksimalkan performa sambil mempertahankan kebenaran. Kueri harus berjalan secepat mungkin tetapi masih menghasilkan hasil yang benar. Dalam beberapa kasus, kebenaran mengharuskan urutan sumber dipertahankan; namun, pemesanan bisa mahal secara komputasi. Oleh karena itu, secara default, PLINQ tidak mempertahankan urutan sumber. Dalam hal ini, PLINQ menyerupai LINQ ke SQL, tetapi tidak seperti LINQ ke Objek, yang mempertahankan pemesanan.
Untuk mengambil alih perilaku default, Anda dapat mengaktifkan pelestarian pesanan dengan menggunakan AsOrdered operator pada urutan sumber. Anda kemudian dapat menonaktifkan pelestarian pesanan nanti dalam kueri dengan menggunakan AsUnordered metode. Dengan kedua metode, kueri diproses berdasarkan heuristik yang menentukan apakah akan menjalankan kueri sebagai paralel atau berurutan. Untuk informasi selengkapnya, lihat Memahami Percepatan di PLINQ.
Contoh berikut menunjukkan kueri paralel yang tidak berurutan yang memfilter semua elemen yang cocok dengan kondisi, tanpa mencoba mengurutkan hasilnya dengan cara apa pun.
var cityQuery =
(from city in cities.AsParallel()
where city.Population > 10000
select city).Take(1000);
Dim cityQuery = From city In cities.AsParallel()
Where city.Population > 10000
Take (1000)
Kueri ini tidak selalu menghasilkan 1000 kota pertama dalam urutan sumber yang memenuhi kondisi, melainkan beberapa set 1000 kota yang memenuhi kondisi tersebut. Operator kueri PLINQ mempartisi urutan sumber ke dalam beberapa sub-urutan yang diproses sebagai tugas bersamaan. Jika pelestarian pesanan tidak ditentukan, hasil dari setiap partisi diserahkan ke tahap kueri berikutnya dalam urutan arbitrer. Selain itu, partisi dapat menghasilkan subset hasilnya sebelum terus memproses elemen yang tersisa. Urutan yang dihasilkan bisa berbeda setiap saat. Aplikasi Anda tidak dapat mengontrol ini karena tergantung pada bagaimana sistem operasi menjadwalkan alur.
Contoh berikut mengambil alih perilaku default dengan menggunakan AsOrdered operator pada urutan sumber. Ini memastikan bahwa Take metode mengembalikan 1000 kota pertama dalam urutan sumber yang memenuhi kondisi.
var orderedCities =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
Dim orderedCities = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Take (1000)
Namun, kueri ini mungkin tidak berjalan secepat versi yang tidak diurutkan karena harus melacak urutan asli di seluruh partisi dan pada waktu penggabungan memastikan bahwa pengurutan konsisten. Oleh karena itu, kami sarankan Anda hanya menggunakan AsOrdered saat diperlukan, dan hanya untuk bagian kueri yang memerlukannya. Ketika pelestarian pesanan tidak lagi diperlukan, gunakan AsUnordered untuk menonaktifkannya. Contoh berikut mencapai ini dengan menyusun dua kueri.
var orderedCities2 =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
var finalResult =
from city in orderedCities2.AsUnordered()
join p in people.AsParallel()
on city.Name equals p.CityName into details
from c in details
select new
{
city.Name,
Pop = city.Population,
c.Mayor
};
foreach (var city in finalResult) { /*...*/ }
Dim orderedCities2 = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Select city
Take (1000)
Dim finalResult = From city In orderedCities2.AsUnordered()
Join p In people.AsParallel() On city.Name Equals p.CityName
Select New With {.Name = city.Name, .Pop = city.Population, .Mayor = city.Mayor}
For Each city In finalResult
Console.WriteLine(city.Name & ":" & city.Pop & ":" & city.Mayor)
Next
Perhatikan bahwa PLINQ mempertahankan urutan yang dihasilkan oleh operator yang memberlakukan pesanan untuk kueri lainnya. Dengan kata lain, operator seperti OrderBy dan ThenBy diperlakukan seolah-olah mereka diikuti dengan panggilan ke AsOrdered.
Operator dan Pengurutan Kueri
Operator kueri berikut memperkenalkan pelestarian pesanan ke dalam semua operasi berikutnya dalam kueri, atau hingga AsUnordered dipanggil:
Operator kueri PLINQ berikut mungkin dalam beberapa kasus memerlukan urutan sumber yang diurutkan untuk menghasilkan hasil yang benar:
Beberapa operator kueri PLINQ bersifat berbeda, tergantung pada apakah urutan sumbernya diurutkan atau tidak diurutkan. Tabel ini menunjukkan operator berikut.
Operator | Hasil ketika urutan sumber diurutkan | Hasil ketika urutan sumber tidak diurutkan |
---|---|---|
Aggregate | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif |
All | Tidak berlaku | Tidak berlaku |
Any | Tidak berlaku | Tidak berlaku |
AsEnumerable | Tidak berlaku | Tidak berlaku |
Average | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif |
Cast | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Concat | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Count | Tidak berlaku | Tidak berlaku |
DefaultIfEmpty | Tidak berlaku | Tidak berlaku |
Distinct | Hasil yang diurutkan | Hasil yang tidak diurutkan |
ElementAt | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
ElementAtOrDefault | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
Except | Hasil yang tidak diurutkan | Hasil yang tidak diurutkan |
First | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
FirstOrDefault | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
ForAll | Menjalankan secara nondeterministik secara paralel | Menjalankan secara nondeterministik secara paralel |
GroupBy | Hasil yang diurutkan | Hasil yang tidak diurutkan |
GroupJoin | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Intersect | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Join | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Last | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
LastOrDefault | Mengembalikan elemen yang ditentukan | Elemen arbitrer |
LongCount | Tidak berlaku | Tidak berlaku |
Min | Tidak berlaku | Tidak berlaku |
OrderBy | Menyusun ulang urutan | Memulai bagian baru yang diurutkan |
OrderByDescending | Menyusun ulang urutan | Memulai bagian baru yang diurutkan |
Range | Tidak berlaku (default yang sama dengan AsParallel ) | Tidak berlaku |
Repeat | Tidak berlaku (default yang sama dengan AsParallel ) | Tidak berlaku |
Reverse | Membalikkan | Tidak melakukan apa-apa |
Select | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Select (diindeks) | Hasil yang diurutkan | Hasil yang tidak diurutkan. |
SelectMany | Hasil yang diurutkan. | Hasil yang tidak diurutkan |
SelectMany (diindeks) | Hasil yang diurutkan. | Hasil yang tidak diurutkan. |
SequenceEqual | Perbandingan yang diurutkan | Perbandingan yang tidak diurutkan |
Single | Tidak berlaku | Tidak berlaku |
SingleOrDefault | Tidak berlaku | Tidak berlaku |
Skip | Melompati elemen n pertama | Melompati elemen n apa pun |
SkipWhile | Hasil yang diurutkan. | Nondeterministic. Melakukan SkipWhile pada urutan arbitrer saat ini |
Sum | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif | Output nondeterministik untuk operasi nonasosiatif atau nonkommutatif |
Take | Mengambil elemen pertama n |
Mengambil elemen apa pun n |
TakeWhile | Hasil yang diurutkan | Nondeterministic. Melakukan SkipWhile pada urutan arbitrer saat ini |
ThenBy | Suplemen OrderBy |
Suplemen OrderBy |
ThenByDescending | Suplemen OrderBy |
Suplemen OrderBy |
ToArray | Hasil yang diurutkan | Hasil yang tidak diurutkan |
ToDictionary | Tidak berlaku | Tidak berlaku |
ToList | Hasil yang diurutkan | Hasil yang tidak diurutkan |
ToLookup | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Union | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Where | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Where (diindeks) | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Zip | Hasil yang diurutkan | Hasil yang tidak diurutkan |
Hasil yang tidak diurutkan tidak secara aktif diacak; mereka tidak memiliki logika pemesanan khusus yang diterapkan padanya. Dalam beberapa kasus, kueri yang tidak berurutan dapat mempertahankan urutan sumber. Untuk kueri yang menggunakan operator Pilih terindeks, PLINQ menjamin bahwa elemen output akan keluar dalam urutan peningkatan indeks, tetapi tidak menjamin indeks mana yang akan ditetapkan ke elemen mana.
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk