PLINQ etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
PLINQ etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

10 Mart 2016 Perşembe

PLINQ

PLINQ

PLINQ .Net Framework 4.0 ile gelen güzel özelliklerden biri. PLINQ çalışmak için Task Parallel Library kütüphanesine kullanır. Klasik Linq ile çok benzeşir.

PLINQ ile çalışabilmek için üzerinde paralel işlem yapılacak olan IEnumerable listesinin hafızada (RAM) yüklü  olması gerekir.

Cancellation ve Exception
Paralel programlama cancellation ve exception önemli iki mevzu. İyi bir çatının bu iki özelliği de kolay kullanılır bir şekilde sunması gerekir.

ParallelEnumerable sınıfı
Bu sınıf verilen bir IEnumerable nesnesini paralel çalışılabilecek hale getiriyor. Aynı zamanda IEnumerable arayüzünün istediği metodları da gerçekleştiriyor.

Kavramlar
Önce kavramlara bakalım.

ParallelEnumerable sınıfı Parallel Aggreation için imkan sunar. Sınıf sayesinde iş küçük parçalara bölünür. Daha sonra Sum(),Aggregate gibi metodlarla sonuçlar birleştirilir.

Parallel Aggregation Nedir
PLINQ ve Aggregation yazısına taşıdım.

Metodlar
Şimdi metodlara göz atalım.

AsParallel metodu
Bu metod verilen listeyi ParallelEnumerable listelerine çevirir.
myList.AsParallel().ForAll(s =>{...});
ParallelEnumerable aslında sadece LINQ metodlarının paralel olarak kullanılabilmesini sağlayan bir wrapper gibi düşünülebilir. Select, Where gibi cümlelerin AsParallel() sonrasında çağrılması gerekir.
Enumerable.Range(0, 1000)
          .AsParallel()
          .Select(...)
          .Where(x => ...);
Şu kullanım şekli yanlıştır.
Enumerable.Range(0, 1000)
          .Select(...)
          .Where(x => ...)
          .AsParallel();

AsParallel metodu dizinin sırasını değiştirir.

PLINQ verilen sorguyu çalıştıtırken IEnumerable listesini bölmek için iki yöntem kullanabilir.
1. Chunk Partitioning
2. Range Partitioning

Her iki yöntemin nasıl çalıştığını gösteren bir şekli burada buldum.

AsOrdered metodu
Bu metod ile girdi olarak verilen veri yapısının sırası çıktıda korunuyor.
myList.AsParallel()
      .AsOrdered()
      .Select(element => ...));
ForEach metodu
Bu metod ile C#'taki foreach döngüsü paralel olarak gerçekleştiriliyor.

WithDegreeOfParallelism metodu
PLINQ otomatik olarak sistemdeki tüm kaynakları kullanmaya çalışır. Eğer kullanılan CPU sayısını sınırlamak gerekirse WithDegreeOfParallelism() metoduna kaç tane CPU kullanılmasını istendiği verilebilir.
Örneği buradan aldım.

PLINQ ile kullanılan her sorgu paralel çalışmak zorunda değildir. Bilhassa .Net 4.5 ve .Net 4.0 arasında bile farklar bulunmakta. Aşağıdaki şekilde mavi ile işaretlenenler paralel çalışmayan sorgu metodları görülebilir.

31 Ekim 2015 Cumartesi

PLINQ ve Aggregation

Giriş
ParallelEnumerable sınıfı Parallel Aggreation için imkan sunar. Sınıf sayesinde iş küçük parçalara bölünür. Daha sonra Sum(),Aggregate gibi metodlarla sonuçlar birleştirilir.

Aggregate ve Seed
Sadece seed almayan aggregate metodları paralel çalışır.
The Aggregate operator’s seeded overloads in their standard incarnations are not parallelizable
Seed almayan bu örnekte faktöriyel alınıyor.
Enumerable.Range(1,n).Select(x => (BigInteger)x).AsParallel().
                                                 Aggregate(BigInteger.Multiply);

Parallel Aggregation Nedir
Bu kavramı şöyle açıklanıyor. Küçük iş parçaları associative (birleşme özelliği, parantezlerin kaldırılması) ve commutative (yer değiştirme özelliği) olmalıdır.

You have a long-running, time-consuming calculation or process you wish to execute, but you want to split the execution across multiple threads to increase the execution speed on multi-core processors. In this case, you can use the parallel aggregation pattern illustrated below if the following conditions are satisfied:

1. The task can be split into multiple, independent parts, each producing a partial result
2. The result of one part is not dependent on the result of another part
3. The set of partial results from each worker thread can be combined (aggregated) when all the threads have finished into a final result
4. The communication between worker threads is minimal-to-none

Yer Değiştirme (Commutative) Özelliği Olmayan İşler İçin Ne Yapılır
İşleri küçük parçalara bölüp Aggregate() metodu ile birleştirirken A,B ve B,A işleminin aynı neticeyi vermediği durumlar da olabilir. Örneğin Aggregate() metodu iki string'i birleştiriyor olsun. A = Hello B = World ise paralellik durumuna göre bazen Hello World bazen de World Hello çıktısını görebiliriz. Bu durumda ne yapılabilir ? Çözümlerden bir tanesi parçalamanın sıralı olmasını sağlamak olabilir. Örnek'te çıktı her zaman sıralama işleminden dolayı
"[7][35][22][6][14]"
string'idir.

var result = new [] { 35, 14, 22, 6, 7 }
    .AsParallel()
    .AsOrdered()
    .Select(c => "[" + c + "]")
    .Aggregate(seed: string.Empty, func: (prev, current) => prev + current);

Console.WriteLine(result);