Rust
SIMD matris
SIMD ile paralel matris çarpımı yaparsın.
Bitirme görevi: SIMD matris
4×4 matris-vektör çarpımını SIMD dostu biçimde yaz. Klasik satır-nokta yaklaşımı her satırda yatay bir indirgeme gerektirir. Sütun yaklaşımı ise yalnızca dikey işlemler kullanır: sonuç vektörü, her sütunun ilgili x bileşeniyle çarpılıp toplanmasıdır (y += sütun_j * x[j], "axpy"):
// y = A·x, A sütun düzeninde: a[j] = j. sütun
fn matvec(a: [[f32; 4]; 4], x: [f32; 4]) -> [f32; 4] {
let mut y = [0.0f32; 4];
for j in 0..4 {
for i in 0..4 { // 4 şeritli dikey çarp-topla
y[i] += a[j][i] * x[j];
}
}
y
}
İç döngü doğrudan tek bir 4 şeritli çarp-topla talimatına eşlenir; yatay işlem gerekmez.
Doğrulama
Optimize edilmiş bir çekirdek her zaman basit bir referans uygulamayla karşılaştırılmalıdır. Satır düzenli matrisle aynı sonucu veren bir referans:
fn matvec_ref(satirlar: [[f32; 4]; 4], x: [f32; 4]) -> [f32; 4] {
satirlar.map(|r| r.iter().zip(&x).map(|(a, b)| a * b).sum())
}
// sütun düzenine çevirmek: devrik
fn devrik(m: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
std::array::from_fn(|j| std::array::from_fn(|i| m[i][j]))
}
Uygulama Matris-vektör
Yukarıdaki matvec, matvec_ref ve devrik fonksiyonlarını yaz. Satır düzeninde [[1,2,0,0],[0,1,0,0],[0,0,2,0],[0,0,0,3]] ve x = [1, 1, 1, 1] için matvec(devrik(A), x) sonucunu {:?} ile ve referansla eşitliğini boşlukla yazdır.
Örnek çözümü göster
fn matvec(a: [[f32; 4]; 4], x: [f32; 4]) -> [f32; 4] {
let mut y = [0.0f32; 4];
for j in 0..4 {
for i in 0..4 {
y[i] += a[j][i] * x[j];
}
}
y
}
fn matvec_ref(satirlar: [[f32; 4]; 4], x: [f32; 4]) -> [f32; 4] {
satirlar.map(|r| r.iter().zip(&x).map(|(a, b)| a * b).sum())
}
fn devrik(m: [[f32; 4]; 4]) -> [[f32; 4]; 4] {
std::array::from_fn(|j| std::array::from_fn(|i| m[i][j]))
}
fn main() {
let a = [
[1.0, 2.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 2.0, 0.0],
[0.0, 0.0, 0.0, 3.0],
];
let x = [1.0; 4];
let y = matvec(devrik(a), x);
println!("{:?} {}", y, y == matvec_ref(a, x));
}
Kendini test et
-
Sütun düzeninde depolamanın bu çarpım için avantajı nedir?
- Daha az bellek
- Daha kolay yazılır
- Avantajı yok
- Her sütun bellekte ardışıktır; tek yüklemeyle bir vektöre sığar
Cevabı göster
Her sütun bellekte ardışıktır; tek yüklemeyle bir vektöre sığar — Veri düzenini algoritmaya göre seçmek, SIMD performansının çoğunu belirler.
-
Dikey çarp-topla
for j in 0..4 {
for i in 0..4 {
y[i] += a[j][i] * x[____];
}
}
Cevabı göster
for j in 0..4 {
for i in 0..4 {
y[i] += a[j][i] * x[j];
}
}
-
Yaklaşım ve özelliği
- Satır-nokta
- Yatay indirgeme ister
- Sütun axpy
- Yalnızca dikey
- Referans uygulama
- Doğrulama
- Devrik
- Düzen dönüşümü
Sıradaki ders: no_std runtime