Bölüm 14: Paralel Algoritmalar
Ç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?
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?
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.
adim = 1, i = 0: a[0] = max(3, 9) = 9. Bu turdaki öteki i'ler aynı anda çalışır.
adim = 1, i = 2: a[2] = max(4, 1) = 4.
adim = 1, i = 4: a[4] = max(5, 2) = 5.
adim = 1, i = 6: a[6] = max(8, 6) = 8.
adim = 2, i = 0: a[0] = max(9, 4) = 9. Bu turdaki öteki i'ler aynı anda çalışır.
adim = 2, i = 4: a[4] = max(5, 8) = 8.
adim = 4, i = 0: a[0] = max(9, 8) = 9.
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 = 1024 | p | T | Maliyet p · T |
|---|---|---|---|
| n işlemci | 1024 | 10 | 10 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?
Amaç kapsayıcı önek toplamı: her i için x₀ + … + xᵢ. Her hücreyi bir işlemci tutuyor.
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.
Tur sonu x = y: artık her hücre 2 öğelik pencerenin toplamı (pencere başta kesilir).
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.
Tur sonu x = y: artık her hücre 4 öğelik pencerenin toplamı (pencere başta kesilir).
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.
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?
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).
t = 0: p0→p1 satır 0: 4 + 2 = 6.
t = 1: p0→p1 satır 1: 2 + 1 = 3; p1→p2 satır 0: 1 + 6 = 7.
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.
t = 3: p1→p2 satır 2: 2 + 4 = 6; p2→p3 satır 1: 1 + 8 = 9.
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örev | Parça | Ara sonuç (map) |
|---|---|---|
| 1 | elma armut | elma 1, armut 1 |
| 2 | elma kiraz | elma 1, kiraz 1 |
| 3 | armut elma muz kiraz | armut 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?
Paylaşılan sayac = 0. İki iş parçacığı (İP1, İP2) birer kez artıracak; beklenen sonuç 2. sayac++ aslında bu üç adımdır.
İP1 okur: t₁ = 0.
İP1 yazmadan önce zamanlayıcı İP2'ye geçer: İP2 de 0 okur.
İP1 kendi yerel kopyasını artırır: t₁ = 1 (bellek hâlâ 0).
İP2 de artırır: t₂ = 1.
İP1 yazar: sayac = 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.