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);

Hiç yorum yok:

Yorum Gönder