CodeBlanks Logo Icon CodeBlanks

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.

Başlangıç kodu

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

Örnek çözüm

main.rs
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::&lt;f32&gt;()</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

Soru
let parcalar = v.chunks_exact(8);
let kalan = parcalar.____();
Cevap
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

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