Mask
- Rust kursu
- Uzman
- Ders 21/46
- 4 dk
Mask ile şartlı paket işlemleri yaparsın.
Mask
SIMD'de karşılaştırmalar tek bir bool değil, şerit başına bir bool içeren bir maske üretir. Maskeler dallanma yerine select ile kullanılır: her şerit için ya bir vektörden ya diğerinden değer alınır. Böylece if olmadan koşullu işlem yapılır:
// nightly std::simd
let a = i32x4::from_array([1, 5, 3, 8]);
let m = a.simd_gt(i32x4::splat(4)); // [false, true, false, true]
let c = m.select(a, i32x4::splat(0)); // [0, 5, 0, 8]Dallanmasız kod, tahmin edilemeyen koşullarda işlemcinin dal tahmin cezasından da kaçınır.
Dizilerle maske ve seçim
Aynı fikri kararlı Rust'ta dizilerle yazabiliriz; yapı derleyicinin vektörleştirebileceği dallanmasız bir biçimdir:
fn buyuk_mu(a: [i32; 4], esik: i32) -> [bool; 4] {
a.map(|x| x > esik)
}
fn sec(m: [bool; 4], a: [i32; 4], b: [i32; 4]) -> [i32; 4] {
std::array::from_fn(|i| if m[i] { a[i] } else { b[i] })
}[T; N]::map, her elemana closure uygulayıp yeni bir dizi döndürür.
Uygulama Maske ve seçim
Yukarıdaki buyuk_mu ve sec fonksiyonlarını yaz. a = [1, 5, 3, 8] ve eşik 4 için maskeyi ve sec(m, a, [0; 4]) sonucunu {:?} ile boşlukla yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
fn buyuk_mu(a: [i32; 4], esik: i32) -> [bool; 4] {
a.map(|x| x > esik)
}
fn sec(m: [bool; 4], a: [i32; 4], b: [i32; 4]) -> [i32; 4] {
std::array::from_fn(|i| if m[i] { a[i] } else { b[i] })
}
fn main() {
let a = [1, 5, 3, 8];
let m = buyuk_mu(a, 4);
println!("{:?} {:?}", m, sec(m, a, [0; 4]));
}Beklenen çıktı
[false, true, false, true] [0, 5, 0, 8]
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Neden SIMD'de <code>if</code> yerine maske kullanılır?
- Gelenek
- Maske gereksizdir
- Şeritler aynı talimatı birlikte çalıştırır; şerit başına ayrı dallanma yoktur Doğru cevap
- if yavaş derlenir
Açıklama: İki dalın sonucu da hesaplanır ve maske hangisinin tutulacağını seçer.
2 Dizi map
fn buyuk_mu(a: [i32; 4], esik: i32) -> [bool; 4] {
a.____(|x| x > esik)
}
fn buyuk_mu(a: [i32; 4], esik: i32) -> [bool; 4] {
a.map(|x| x > esik)
}
Açıklama: Dizi üzerinde map aynı boyutlu yeni bir dizi döndürür.
3 İşlem ve sonuç (a = [1, 5, 3, 8])
| Kavram | Anlamı |
|---|---|
a > 4 |
[false, true, false, true] |
sec(m, a, [0; 4]) |
[0, 5, 0, 8] |
a > 0 |
[true, true, true, true] |
a > 10 |
[false, false, false, false] |