Bölüm 14: Paralel Algoritmalar

Bölüm 14: Paralel Algoritmalar · Çalışma Soruları
Flynn ve PRAMHızlanma, verimlilik, Amdahlİş ve derinlikPRAM ile indirgemeÖnek toplamıBoru hattıFork/Join ve MapReduceYarış durumu
Sercan KÜLCÜ

Çoktan Seçmeli · Modeller ve Ölçütler

Soru 1: PRAM Türü

Bir PRAM algoritmasında aynı turda birçok işlemci aynı bellek hücresini okuyabiliyor, ama bir hücreye aynı turda yalnızca tek işlemci yazabiliyor. Bu hangi PRAM türüdür?

C: CREW = Concurrent Read, Exclusive Write. EREW'de okuma da dışlayıcıdır; CRCW'de eşzamanlı yazma da serbesttir ve çakışmalar bir kuralla (ortak değer, öncelik, rastgele) çözülür. PRAM ağaç toplamı EREW ile yetinir.

Çoktan Seçmeli · Modeller ve Ölçütler

Soru 2: Amdahl Yasası

Bir programın %75'i paralelleştirilebiliyor. Amdahl yasasına göre p = 3 işlemcide hızlanma ve işlemci sayısı sonsuza giderken üst sınır nedir?

sınır 4p = 3: S = 2işlemci sayısı p (1 … 32)

A: S = 1 / ((1 − f) + f/p) = 1 / (0,25 + 0,25) = 2; p → ∞ iken S → 1 / (1 − f) = 1 / 0,25 = 4. 2,25 = f · p yalnızca paralel kısmı hızlandırır, sıralı kısmı unutur. Sıralı %25 hızlanmayı 4 ile sınırlar.

Çoktan Seçmeli · Modeller ve Ölçütler

Soru 3: Gustafson Yasası

Problem boyutu işlemci sayısıyla birlikte büyütülüyor. Paralel kesir f = 0,8 ve p = 10 iken Gustafson yasasına göre ölçeklenmiş hızlanma kaçtır?

D: S = (1 − f) + f · p = 0,2 + 8 = 8,2. 3,6 Amdahl'ın sonucudur (1 / (0,2 + 0,08) ≈ 3,57): sabit boyutlu problem. 5,0 Amdahl sınırıdır (1 / 0,2). Büyük problemlerde sıralı kısmın payı küçüldüğü için paralellik daha kârlıdır.

Çıktı Sorusu · Modeller ve Ölçütler

Soru 4: İş, Derinlik ve Brent

n = 256 sayı dengeli ikili ağaçla toplanıyor. İş W, derinlik D ve paralellik W / D nedir? p = 16 işlemcide Brent teoremi Tp için hangi üst sınırı verir; alt sınırlar nelerdir?

Cevabı göster
  • W = n − 1 = 255 toplama; D = log₂ 256 = 8 tur; paralellik 255 / 8 ≈ 31,9 (≈ 32 işlemciden fazlası yarar sağlamaz).
  • Brent: T₁₆ ≤ W/p + D = 255/16 + 8 ≈ 15,9 + 8 = 23,9 → 24 adım.
  • Alt sınırlar: T₁₆ ≥ W/p ≈ 15,9 ve T₁₆ ≥ D = 8 → T₁₆ ≥ 16.

16 ≤ T₁₆ ≤ 24: Brent sınırı alt sınırın en çok 2 katıdır.

Çoktan Seçmeli · Modeller ve Ölçütler

Soru 5: Süre Sınırları

Bir paralel algoritmanın işi W = 1000, derinliği D = 50. p = 10 işlemcide Tp için hangi aralık kesin olarak doğrudur?

B: Alt sınırlar Tp ≥ W/p = 100 ve Tp ≥ D = 50 → T ≥ 100. Brent üst sınırı Tp ≤ W/p + D = 150. 100'e tam eşitlik ancak hiç bekleme olmazsa sağlanır, garanti değildir.

Adım Adım Çalıştırma · PRAM ile İndirgeme

Soru 6: PRAM ile En Büyük Öğe

PRAM ağaç toplamı, toplama yerine en büyüğü alacak biçimde değiştirildi. Turlar boyunca dizi nasıl değişir, sonuç ve tur sayısı nedir?

3091421354258667

Toplamadaki ağaç, toplama yerine Math.max ile en büyük öğeyi bulur (birleşmeli her işlem olur). Her hücreyi bir işlemci tutuyor.

9091421354258667

adim = 1, i = 0: a[0] = max(3, 9) = 9. Bu turdaki öteki i'ler aynı anda çalışır.

9091421354258667

adim = 1, i = 2: a[2] = max(4, 1) = 4.

9091421354258667

adim = 1, i = 4: a[4] = max(5, 2) = 5.

9091421354258667

adim = 1, i = 6: a[6] = max(8, 6) = 8.

9091421354258667

adim = 2, i = 0: a[0] = max(9, 4) = 9. Bu turdaki öteki i'ler aynı anda çalışır.

9091421384258667

adim = 2, i = 4: a[4] = max(5, 8) = 8.

9091421384258667

adim = 4, i = 0: a[0] = max(9, 8) = 9.

9091421384258667

adim = 8 → döngü biter. En büyük a[0] = 9: log₂ 8 = 3 tur, 4 + 2 + 1 = 7 karşılaştırma (W = n − 1, D = log₂ n). Soluk hücreler artık okunmaz.

int[] a = {3, 9, 4, 1, 5, 2, 8, 6};
int n = a.length;
for (int adim = 1; adim < n; adim *= 2) {
  // aynı turdaki tüm i'ler paralel
  for (int i = 0; i + adim < n; i += 2 * adim)
    a[i] = Math.max(a[i], a[i + adim]);
}  // tur sonu: senkronizasyon
// en büyük a[0]'da

Çıktı Sorusu · PRAM ile İndirgeme

Soru 7: İkinin Kuvveti Olmayan n

Ağaç toplamı kodu a = {4, 2, 7, 1, 3, 5} (n = 6) dizisiyle çalıştırılıyor. Her turda hangi toplamalar yapılır; sonunda a[0] ve dizi nedir? Toplam kaç toplama ve kaç tur?

int n = a.length;
for (int adim = 1; adim < n; adim *= 2) {
  // aynı turdaki tüm i'ler paralel
  for (int i = 0; i + adim < n; i += 2 * adim)
    a[i] = a[i] + a[i + adim];
}  // tur sonu: senkronizasyon
Cevabı göster
  • adim = 1: i = 0, 2, 4 → a[0] = 6, a[2] = 8, a[4] = 8 → [6, 2, 8, 1, 8, 5]
  • adim = 2: i = 0 → a[0] = 6 + 8 = 14; i = 4'te 4 + 2 < 6 sağlanmaz
  • adim = 4: i = 0 → a[0] = 14 + 8 = 22

Dizi [22, 2, 8, 1, 8, 5], a[0] = 22 = 4 + 2 + 7 + 1 + 3 + 5. 5 toplama (= n − 1), 3 tur (= ⌈log₂ 6⌉). i + adim < n koşulu eşi olmayan hücreyi (a[4]) bir sonraki tura bırakır.

Klasik Soru · PRAM ile İndirgeme

Soru 8: Maliyet-Optimal Toplama

n işlemcili PRAM ağaç toplamı neden maliyet-optimal değildir? p = n / log₂ n işlemciyle nasıl maliyet-optimal yapılır? n = 1024 için iki sürümün işlemci sayısı, süresi ve maliyetini karşılaştırın.

Cevabı göster

n işlemciyle T = log₂ n, maliyet p · T = n log₂ n; en iyi sıralı algoritma Θ(n). Turlar ilerledikçe işlemcilerin çoğu boşta bekler.

Düzeltme: her işlemci önce kendi log₂ n'lik bloğunu sıralı toplar (O(log n)), sonra n / log₂ n kısmi toplam ağaçla birleştirilir (O(log n)). Maliyet (n / log n) · O(log n) = Θ(n).

n = 1024pTMaliyet p · T
n işlemci10241010 240
n / log₂ n≈ 102≈ 9 + 7 = 16≈ 1 632 = Θ(n)

İkinci sürümde süre biraz uzar (bloğu toplamak 9 adım, 102 kısmi toplamın ağacı ⌈log₂ 102⌉ = 7 tur), ama işlemci-zaman 6 kat azalır.

Adım Adım Çalıştırma · Önek Toplamı

Soru 9: Hillis–Steele İzleme

Hillis–Steele önek toplamı [3, 1, 4, 1, 5, 9, 2, 6] dizisine uygulanıyor. Her turda hangi değerler hesaplanır, kaç toplama yapılır?

3011421354952667

Amaç kapsayıcı önek toplamı: her i için x₀ + … + xᵢ. Her hücreyi bir işlemci tutuyor.

314159263455614118yx

d = 1: i ≥ 1 olan 7 işlemci aynı anda y[i] = x[i] + x[i − 1] hesaplar (çizgiler okunan iki hücre). Okumalar eski x'ten yapılır.

304152536414511687

Tur sonu x = y: artık her hücre 2 öğelik pencerenin toplamı (pencere başta kesilir).

3455614118348911191722yx

d = 2: i ≥ 2 olan 6 işlemci aynı anda y[i] = x[i] + x[i − 2] hesaplar (çizgiler okunan iki hücre). Okumalar eski x'ten yapılır.

30418293114195176227

Tur sonu x = y: artık her hücre 4 öğelik pencerenin toplamı (pencere başta kesilir).

348911191722348914232531yx

d = 4: i ≥ 4 olan 4 işlemci aynı anda y[i] = x[i] + x[i − 4] hesaplar (çizgiler okunan iki hücre). Okumalar eski x'ten yapılır.

30418293144235256317

Sonuç [3, 4, 8, 9, 14, 23, 25, 31]. log₂ 8 = 3 tur (D), ama 7 + 6 + 4 = 17 toplama (W = O(n log n)); sıralı algoritma 7 toplama yapar: iş-verimli değil.

int[] x = {3, 1, 4, 1, 5, 9, 2, 6};
int n = x.length;
for (int d = 1; d < n; d *= 2) {
  int[] y = x.clone();  // tur başı kopya
  for (int i = d; i < n; i++)  // hepsi paralel
    y[i] = x[i] + x[i - d];
  x = y;  // senkronizasyon
}

Çıktı Sorusu · Önek Toplamı

Soru 10: Kopyasız Önek Toplamı

Hillis–Steele kodunda tur başı kopya kaldırılıp hesap aynı dizi üzerinde yapılıyor. {2, 4, 1, 3, 5} için çıktı nedir, doğru önek toplamı nedir? Hata neden kaynaklanır?

int[] x = {2, 4, 1, 3, 5};
int n = x.length;
for (int d = 1; d < n; d *= 2)
  for (int i = d; i < n; i++)
    x[i] += x[i - d];  // kopya yok!
System.out.println(Arrays.toString(x));
Cevabı göster

Çıktı: [2, 6, 9, 16, 26]; doğrusu [2, 6, 7, 10, 15].

  • d = 1: i artan sırayla gezilir; x[2] += x[1] okunduğunda x[1] bu turda zaten güncellenmiştir → tek turda sıralı önek oluşur: [2, 6, 7, 10, 15].
  • d = 2 ve d = 4 turları bu doğru sonuca yeniden ekler: [2, 6, 9, 16, 24] → [2, 6, 9, 16, 26].

PRAM'da bir turdaki tüm okumalar yazmalardan önce olur; sıralı simülasyonda bunu kopya (ya da i'yi azalan sırada gezmek) sağlar. Gerçek paralel kodda bu, turlar arası senkronizasyon (bariyer) unutulunca ortaya çıkan yarışa karşılık gelir.

Adım Adım Çalıştırma · Boru Hattı

Soru 11: Boru Hattı İzleme

p = 4 işlemci, m = 3 satır; sütunlar p0: (2, 1, 3), p1: (4, 2, 1), p2: (1, 5, 2), p3: (3, 1, 4). Boru hattı kodu her adımda hangi toplamaları yapar?

p0213p1421p2152p3314r0r1r2

4 işlemci zincir (p0 → p1 → p2 → p3), her biri 3 satırlık bir sütun tutuyor. Hedef: her satırda pj, p0 … pj toplamını tutsun. p0'ın değerleri zaten sonuçtur (yeşil).

p0213p1621p2152p3314r0r1r2

t = 0: p0→p1 satır 0: 4 + 2 = 6.

p0213p1631p2752p3314r0r1r2

t = 1: p0→p1 satır 1: 2 + 1 = 3; p1→p2 satır 0: 1 + 6 = 7.

p0213p1634p2782p31014r0r1r2

t = 2: p0→p1 satır 2: 1 + 3 = 4; p1→p2 satır 1: 5 + 3 = 8; p2→p3 satır 0: 3 + 7 = 10.

p0213p1634p2786p31094r0r1r2

t = 3: p1→p2 satır 2: 2 + 4 = 6; p2→p3 satır 1: 1 + 8 = 9.

p0213p1634p2786p310910r0r1r2

t = 4: p2→p3 satır 2: 4 + 6 = 10. Bitti: m + p − 2 = 5 adım (saf yöntem m(p − 1) = 9); p3 satır toplamlarını (10, 9, 10) tutar.

for (int t = 0; t < m + p - 2; t++)
  // tüm j'ler aynı anda
  for (int j = 0; j < p - 1; j++) {
    int r = t - j;
    if (r >= 0 && r < m)
      x[j + 1][r] += x[j][r];
  }

Çoktan Seçmeli · Boru Hattı

Soru 12: Boru Hattı Adım Sayısı

Doğrusal zincirdeki boru hattında p = 6 işlemci ve m = 50 satır var. Boru hattıyla kaç adım gerekir; satırları tek tek zincir boyunca taşıyan saf yöntem kaç adım sürer?

B: Boru hattı m + p − 2 = 54 adım; saf yöntem her satırı p − 1 = 5 adımda taşır: m(p − 1) = 250. 50, hattın dolma süresini unutmaktır. Verimlilik m / (m + p − 2) = 50/54 ≈ 0,93: m ≫ p iken 1'e yaklaşır.

Çoktan Seçmeli · Fork/Join ve MapReduce

Soru 13: Paralel Birleştirme Sıralamasının Derinliği

İki yarıyı paralel sıralayıp sıralı birleştiren Fork/Join birleştirme sıralaması için derinlik D(n) ve paralellik W / D nedir?

D: İki yarı paralel olduğu için D(n) = D(n/2) + Θ(n) (birleştirme sıralı) = Θ(n); W = Θ(n log n) → paralellik Θ(log n): n = 10⁶ için ≈ 20 çekirdekten fazlası pek yararlı olmaz. B tamamen sıralı sürümdür; C ise birleştirmenin de O(log n) derinlikte paralel yapıldığı sürüme aittir.

Çıktı Sorusu · Fork/Join ve MapReduce

Soru 14: MapReduce Kelime Sayma

Kelimeler: "elma armut elma kiraz armut elma muz kiraz" (8 kelime). 3 map görevi var; parça boyu ⌊8/3⌋ = 2, son görev kalan tüm kelimeleri alıyor. Her map görevinin ara sonucu ve reduce sonrası toplam nedir?

protected Map<String, Integer> compute() {
  Map<String, Integer> sonuc = new HashMap<>();
  for (String kelime : parca)
    sonuc.merge(kelime, 1, Integer::sum);
  return sonuc;
}
// Reduce
for (Map<String, Integer> m : ara)
  m.forEach((k, v) ->
      toplam.merge(k, v, Integer::sum));
Cevabı göster
GörevParçaAra sonuç (map)
1elma armutelma 1, armut 1
2elma kirazelma 1, kiraz 1
3armut elma muz kirazarmut 1, elma 1, muz 1, kiraz 1

Reduce (merge(k, v, Integer::sum)): elma 3, armut 2, kiraz 2, muz 1.

Her map görevinin kendi HashMap'i olduğu için paylaşılan durum ve kilit yoktur. Son görev 4 kelime aldığı için yük dengesizdir; HashMap yineleme sırası tanımsız olduğundan yazdırma sırası farklı çıkabilir.

Adım Adım Çalıştırma · Yarış Durumu

Soru 15: Kayıp Güncelleme

İki iş parçacığı paylaşılan sayac'ı aşağıdaki sırayla iç içe geçerek artırıyor: İP1 oku, İP2 oku, İP1 artır, İP2 artır, İP1 yaz, İP2 yaz. sayac sonunda kaçtır?

sayac0İP1: t = —İP2: t = —

Paylaşılan sayac = 0. İki iş parçacığı (İP1, İP2) birer kez artıracak; beklenen sonuç 2. sayac++ aslında bu üç adımdır.

sayac0İP1: t = 0İP2: t = —

İP1 okur: t₁ = 0.

sayac0İP1: t = 0İP2: t = 0

İP1 yazmadan önce zamanlayıcı İP2'ye geçer: İP2 de 0 okur.

sayac0İP1: t = 1İP2: t = 0

İP1 kendi yerel kopyasını artırır: t₁ = 1 (bellek hâlâ 0).

sayac0İP1: t = 1İP2: t = 1

İP2 de artırır: t₂ = 1.

sayac1İP1: t = 1İP2: t = 1

İP1 yazar: sayac = 1.

sayac1İP1: t = 1İP2: t = 1

İP2 yazar: sayac = 1. İP1'in artışı kayboldu (lost update): sonuç 1. Çözüm: AtomicInteger.incrementAndGet(), synchronized ya da her görevin yerel sonucu + birleştirme.

// İş parçacığı 1 ve 2 aynı kodu çalıştırır:
int t = sayac;  // oku
t = t + 1;  // artır
sayac = t;  // yaz

Çoktan Seçmeli · Yarış Durumu

Soru 16: Yarışın Sonucu

İki iş parçacığının her biri paylaşılan int sayac değişkenini (başta 0) senkronizasyonsuz olarak sayac++ ile 1000'er kez artırıyor. Program bitince sayac için hangisi kesin olarak doğrudur?

A: Her kayıp güncelleme bir artışı siler, değer asla eklenmez: sonuç ≤ 2000, ama zamanlamaya bağlı olarak (her çalıştırmada farklı) daha küçük olabilir. Hata her çalıştırmada görülmeyebilir; bu yüzden yarış durumları zor ayıklanır.

Çoktan Seçmeli · Yarış Durumu

Soru 17: Güvenli Ziyaret Kümesi

Eşzamanlı çizge gezinmesinde birçok görev aynı ziyaret kümesini paylaşıyor. Bir düğümün yalnızca bir kez gezilmesini hangi kod garanti eder?

C: Eşzamanlı küme ve add'in dönüş değeri kontrol ile eklemeyi tek atomik işlem yapar. B'de küme güvenli olsa da contains ile add arasında başka bir görev aynı düğümü ekleyebilir (iki ayrı adım). HashSet eşzamanlı yazmada iç yapısı bozulabileceği için A ve D güvenli değildir.

Klasik Soru · Yarış Durumu

Soru 18: Paralelleştirilemeyen Döngü

Aşağıdaki iki döngüden hangisi PRAM'da O(log n) derinlikte paralelleştirilebilir, hangisi paralelleştirilemez? Neden? (a) for i: y[i] = y[i − 1] + x[i] (b) for i: x[i] = f(x[i − 1]), f keyfi bir fonksiyon.

Cevabı göster

İkisi de veri bağımlılığı (adım i, adım i − 1'i bekler) içeriyor gibi görünür, ama:

  • (a) önek toplamıdır. Toplama birleşmeli olduğu için parantezler değiştirilebilir: Hillis–Steele (W = O(n log n)) ya da Blelloch (W = O(n)) ile D = O(log n).
  • (b) keyfi f için birleşmeli bir "birleştirme" işlemi yoktur: x[i]'yi bilmek için x[i − 1] gerçekten hesaplanmış olmalıdır. Bağımlılık zinciri n uzunluğundadır: D = Θ(n), paralellik 1.

Genel kural: derinlik, en uzun bağımlılık zinciridir. Birleşmeli bir işlem zinciri ağaca çevirmeye izin verir (indirgeme, tarama); keyfi yineleme vermez.

Son

Bölüm 14: Paralel Algoritmalar: Çalışma Soruları
Konu anlatımı: Paralel Algoritmalar sunumu · Terim sözlüğü
1 / 1 Sercan KÜLCÜ, Tüm hakları saklıdır.