Auto-vectorization
- Rust kursu
- Uzman
- Ders 23/46
- 4 dk
Derleyicinin otomatik vektörizasyonunu öğrenirsin.
Auto-vectorization
LLVM, uygun döngüleri kendiliğinden SIMD talimatlarına çevirir. Yardımcı olan koşullar: sınır denetimi olmayan erişim (yineleyiciler, chunks_exact), dallanmasız gövde, bağımsız şeritler. Engelleyenler: döngüler arası bağımlılık, erken çıkış, kayan nokta toplamasının sırası.
// vektörleşmeye uygun: 8 ayrı birikim
fn toplam(v: &[f32]) -> f32 {
let mut birikim = [0.0f32; 8];
let parcalar = v.chunks_exact(8);
let kalan = parcalar.remainder();
for p in parcalar {
for i in 0..8 { birikim[i] += p[i]; }
}
birikim.iter().sum::<f32>() + kalan.iter().sum::<f32>()
}Hedef özellikleri
Varsayılan derleme tüm x86-64 işlemcilerde çalışacak (SSE2) talimatlar kullanır. Belirli bir makine için daha geniş vektörler açılabilir:
$ RUSTFLAGS="-C target-cpu=native" cargo build --release
// ya da yalnızca bir fonksiyon için, çalışma anı denetimiyle:
#[target_feature(enable = "avx2")]
unsafe fn hizli_toplam(v: &[f32]) -> f32 { .. }
if is_x86_feature_detected!("avx2") { unsafe { hizli_toplam(&v) } } else { .. }target-cpu=native ile derlenen ikili, daha eski işlemcilerde çalışmayabilir.
Uygulama Vektörleşebilir toplam
Yukarıdaki toplam fonksiyonunu 8 birikimle yaz. 1'den 100'e kadar sayıları f32 olarak içeren bir vektörün toplamını yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
fn toplam(v: &[f32]) -> f32 {
let mut birikim = [0.0f32; 8];
let parcalar = v.chunks_exact(8);
let kalan = parcalar.remainder();
for p in parcalar {
for i in 0..8 {
birikim[i] += p[i];
}
}
birikim.iter().sum::<f32>() + kalan.iter().sum::<f32>()
}
fn main() {
let v: Vec<f32> = (1..=100).map(|x| x as f32).collect();
println!("{}", toplam(&v));
}Beklenen çıktı
5050
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Neden <code>v.iter().sum::<f32>()</code> çoğu zaman vektörleşmez?
- Tek birikim değişkeni sıralı bir bağımlılık zinciri oluşturur ve f32 sırası değiştirilemez Doğru cevap
- sum yavaştır
- Vektörleşir
- f32 desteklenmez
Açıklama: Çoklu birikim, sırayı açıkça değiştirme iznini kodun kendisine yazmaktır.
2 Artanlar
let parcalar = v.chunks_exact(8);
let kalan = parcalar.____();
let parcalar = v.chunks_exact(8);
let kalan = parcalar.remainder();
Açıklama: remainder tam parçalara sığmayan son elemanları verir.
3 Desen ve vektörleşme
| Kavram | Anlamı |
|---|---|
chunks_exact + birikim dizisi |
Uygun |
Tek f32 birikimi |
Genellikle vektörleşmez |
Gövdede break |
Engeller |
target-cpu=native |
Geniş vektörler |