Rust
Auto-vectorization
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.
Örnek çözümü göster
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));
}
Kendini test et
-
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
- sum yavaştır
- Vektörleşir
- f32 desteklenmez
Cevabı göster
Tek birikim değişkeni sıralı bir bağımlılık zinciri oluşturur ve f32 sırası değiştirilemez — Çoklu birikim, sırayı açıkça değiştirme iznini kodun kendisine yazmaktır.
-
Artanlar
let parcalar = v.chunks_exact(8);
let kalan = parcalar.____();
Cevabı göster
let parcalar = v.chunks_exact(8);
let kalan = parcalar.remainder();
-
Desen ve vektörleşme
- chunks_exact + birikim dizisi
- Uygun
- Tek f32 birikimi
- Genellikle vektörleşmez
- Gövdede break
- Engeller
- target-cpu=native
- Geniş vektörler
Sıradaki ders: Özet - SIMD