PLINQ'te Sıra Koruma
PLINQ'ta amaç, doğruluğu korurken performansı en üst düzeye çıkarmaktır. Sorgu mümkün olduğunca hızlı çalışmalı ancak yine de doğru sonuçları üretmelidir. Bazı durumlarda doğruluk, kaynak dizisinin sırasının korunmasını gerektirir; ancak sıralama işlem açısından pahalı olabilir. Bu nedenle, PLINQ varsayılan olarak kaynak dizisinin sırasını korumaz. Bu bağlamda PLINQ, LINQ to SQL'e benzer, ancak sıralamayı koruyan LINQ to Objects'den farklı bir özelliktir.
Varsayılan davranışı geçersiz kılmak için, kaynak dizideki işlecini kullanarak sipariş korumayı AsOrdered açabilirsiniz. Daha sonra sorgunun devamında yöntemini kullanarak sipariş korumasını AsUnordered kapatabilirsiniz. Her iki yöntemle de sorgu, sorgunun paralel mi yoksa sıralı olarak mı yürütüleceğini belirleyen buluşsal yöntemlere göre işlenir. Daha fazla bilgi için bkz . PLINQ'te Hızlandırmayı Anlama.
Aşağıdaki örnek, sonuçları herhangi bir şekilde sıralamaya çalışmadan bir koşulla eşleşen tüm öğeler için filtreleyen sıralanmamış bir paralel sorguyu gösterir.
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)
Bu sorgu, koşula uyan kaynak dizideki ilk 1000 şehri değil, koşulu karşılayan 1000 şehirden oluşan bir küme oluşturmak zorunda değildir. PLINQ sorgu işleçleri, kaynak diziyi eşzamanlı görev olarak işlenen birden çok alt diziye böler. Sıra koruma belirtilmezse, her bölümden alınan sonuçlar rastgele bir sırada sorgunun bir sonraki aşamasına teslim edilir. Ayrıca, bir bölüm kalan öğeleri işlemeye devam etmeden önce sonuçlarının bir alt kümesini verebilir. Sonuçta elde edilen sıra her seferinde farklı olabilir. İşletim sisteminin iş parçacıklarını nasıl zamanladığına bağlı olduğundan uygulamanız bunu denetleyemiyor.
Aşağıdaki örnek, kaynak dizideki işlecini AsOrdered kullanarak varsayılan davranışı geçersiz kılar. Bu, yöntemin Take , koşulu karşılayan kaynak dizideki ilk 1000 şehri döndürmesini sağlar.
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)
Ancak, bölümler boyunca özgün sıralamayı izlemesi ve birleştirme sırasında sıralamanın tutarlı olduğundan emin olması gerektiğinden, bu sorgu büyük olasılıkla sıralanmamış sürüm kadar hızlı çalışmaz. Bu nedenle, yalnızca gerekli olduğunda ve yalnızca sorgunun gerektiren bölümleri için kullanmanızı AsOrdered öneririz. Sipariş koruması artık gerekli olmadığında, kapatmak için kullanın AsUnordered . Aşağıdaki örnek, iki sorgu oluşturarak bunu başarıyor.
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
PLINQ'un sorgunun geri kalanı için order-imposing işleçleri tarafından üretilen bir sıranın sıralamasını koruduğuna dikkat edin. Başka bir AsOrdereddeyişle ve ThenBy gibi OrderBy işleçler, çağrısı tarafından takip edilmiş gibi değerlendirilir.
Sorgu İşleçleri ve Sıralama
Aşağıdaki sorgu işleçleri, sorgudaki sonraki tüm işlemlere veya çağrılana kadar AsUnordered sipariş korumasını tanıtır:
Aşağıdaki PLINQ sorgu işleçleri bazı durumlarda doğru sonuçlar üretmek için sıralı kaynak dizileri gerektirebilir:
Bazı PLINQ sorgu işleçleri, kaynak sıralarının sıralı veya sırasız olmasına bağlı olarak farklı davranır. Aşağıdaki tabloda bu işleçler listelenmiştir.
Operatör | Kaynak dizisi sıralandığında elde edilen sonuç | Kaynak dizisi sıralanmadığında elde edilen sonuç |
---|---|---|
Aggregate | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış |
All | Uygulanamaz | Uygulanamaz |
Any | Uygulanamaz | Uygulanamaz |
AsEnumerable | Uygulanamaz | Uygulanamaz |
Average | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış |
Cast | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Concat | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Count | Uygulanamaz | Uygulanamaz |
DefaultIfEmpty | Uygulanamaz | Uygulanamaz |
Distinct | Sıralı sonuçlar | Sıralanmamış sonuçlar |
ElementAt | Belirtilen öğeyi döndür | Rastgele öğe |
ElementAtOrDefault | Belirtilen öğeyi döndür | Rastgele öğe |
Except | Sıralanmamış sonuçlar | Sıralanmamış sonuçlar |
First | Belirtilen öğeyi döndür | Rastgele öğe |
FirstOrDefault | Belirtilen öğeyi döndür | Rastgele öğe |
ForAll | Paralel olarak belirsiz bir şekilde yürütür | Paralel olarak belirsiz bir şekilde yürütür |
GroupBy | Sıralı sonuçlar | Sıralanmamış sonuçlar |
GroupJoin | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Intersect | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Join | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Last | Belirtilen öğeyi döndür | Rastgele öğe |
LastOrDefault | Belirtilen öğeyi döndür | Rastgele öğe |
LongCount | Uygulanamaz | Uygulanamaz |
Min | Uygulanamaz | Uygulanamaz |
OrderBy | Sırayı yeniden sıralar | Yeni sıralı bölümü başlatır |
OrderByDescending | Sırayı yeniden sıralar | Yeni sıralı bölümü başlatır |
Range | Geçerli değil (ile aynı varsayılan AsParallel ) | Uygulanamaz |
Repeat | Geçerli değil (ile aynı varsayılan AsParallel) | Uygulanamaz |
Reverse | Ters -ine çevirir | Hiçbir şey yapılmaz |
Select | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Select (dizine alınan) | Sıralı sonuçlar | Sıralanmamış sonuçlar. |
SelectMany | Sıralı sonuçlar. | Sıralanmamış sonuçlar |
SelectMany (dizine alınan) | Sıralı sonuçlar. | Sıralanmamış sonuçlar. |
SequenceEqual | Sıralı karşılaştırma | Sıralanmamış karşılaştırma |
Single | Uygulanamaz | Uygulanamaz |
SingleOrDefault | Uygulanamaz | Uygulanamaz |
Skip | İlk n öğeyi atlar | Herhangi bir n öğeyi atlar |
SkipWhile | Sıralı sonuçlar. | Nondeterministic. Geçerli rastgele sırada SkipWhile gerçekleştirir |
Sum | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış | İlişkisiz veya ticari olmayan işlemler için belirsiz çıkış |
Take | İlk n öğeleri alır |
Herhangi bir n öğeyi alır |
TakeWhile | Sıralı sonuçlar | Nondeterministic. Geçerli rastgele sırada TakeWhile gerçekleştirir |
ThenBy | Takviye -leri OrderBy |
Takviye -leri OrderBy |
ThenByDescending | Takviye -leri OrderBy |
Takviye -leri OrderBy |
ToArray | Sıralı sonuçlar | Sıralanmamış sonuçlar |
ToDictionary | Uygulanamaz | Uygulanamaz |
ToList | Sıralı sonuçlar | Sıralanmamış sonuçlar |
ToLookup | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Union | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Where | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Where (dizine alınan) | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Zip | Sıralı sonuçlar | Sıralanmamış sonuçlar |
Sıralanmamış sonuçlar etkin olarak karıştırılmaz; yalnızca kendilerine herhangi bir özel sıralama mantığı uygulanmaz. Bazı durumlarda, sıralanmamış bir sorgu kaynak dizinin sırasını koruyabilir. Dizine alınan Select işlecini kullanan sorgular için PLINQ, çıkış öğelerinin artan dizin sırasına göre çıkarılacağını garanti eder, ancak hangi dizinlerin hangi öğelere atanacağı konusunda hiçbir garanti vermemektedir.