CodeBlanks Logo Icon CodeBlanks

Horizontal işlemler

horizontal_reduce gibi yatay işlemleri kullanırsın.

Horizontal işlemler

Şerit bazlı işlemler "dikey"dir (şerit i ile şerit i). Bir vektörün kendi şeritlerini birleştiren işlemler ise "yatay"dır: reduce_sum, reduce_max, reduce_and. Yatay işlemler pahalıdır, bu yüzden döngünün sonunda bir kez yapılır:

// nightly std::simd
let v = f32x8::from_array([1., 2., 3., 4., 5., 6., 7., 8.]);
let t = v.reduce_sum();   // 36
let m = v.reduce_max();   // 8

Donanım bunu genellikle "ağaç" biçiminde yapar: önce yarıları toplar, sonra çeyrekleri, en sonda tek değer kalır.

Ağaç indirgemesi

Şeritleri yarıya katlayarak toplamak, yatay indirgemenin nasıl çalıştığını gösterir:

fn yatay_toplam(v: [f32; 8]) -> f32 {
    let d4: [f32; 4] = std::array::from_fn(|i| v[i] + v[i + 4]);
    let d2: [f32; 2] = std::array::from_fn(|i| d4[i] + d4[i + 2]);
    d2[0] + d2[1]
}

Her adımda dizinin yarısı diğer yarısıyla şerit bazlı toplanır; 8 → 4 → 2 → 1.

Uygulama Yatay toplam

Yukarıdaki yatay_toplam fonksiyonunu yaz. [1.0, 2.0, ..., 8.0] için sonucu ve fold(f32::MIN, f32::max) ile bulduğun en büyük şeriti boşlukla yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
fn yatay_toplam(v: [f32; 8]) -> f32 {
    let d4: [f32; 4] = std::array::from_fn(|i| v[i] + v[i + 4]);
    let d2: [f32; 2] = std::array::from_fn(|i| d4[i] + d4[i + 2]);
    d2[0] + d2[1]
}

fn main() {
    let v = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
    let m = v.iter().copied().fold(f32::MIN, f32::max);
    println!("{} {}", yatay_toplam(v), m);
}

Beklenen çıktı

36 8

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Ağaç biçimli toplama, soldan sağa toplamayla aynı sonucu verir mi (f32)?

  • Yalnızca tamsayıda farklı
  • Her zaman değil; kayan nokta toplaması birleşmeli değildir, küçük farklar olabilir Doğru cevap
  • Her zaman aynı
  • Hiçbir zaman

Açıklama: Derleyici bu yüzden f32 toplama döngülerini kendiliğinden yeniden sıralamaz; açık izin (ya da elle çoklu birikim) gerekir.

2 Yarıya katla

Soru
let d4: [f32; 4] = std::array::from_fn(|i| v[i] + v[i + ____]);
Cevap
let d4: [f32; 4] = std::array::from_fn(|i| v[i] + v[i + 4]);

Açıklama: 8 şeritli dizi, i ile i + 4 toplanarak 4 şeride iner.

3 İşlem ve yönü

Kavram Anlamı
a + b Dikey
reduce_sum Yatay
reduce_max Yatay (en büyük)
splat Yayma

Uzman bölümündeki tüm dersler