Arc<T>
- Rust kursu
- İleri seviye
- Ders 16/81
- 4 dk
Arc<T> ile iş parçacıkları arasında veri paylaşırsın.
Arc<T>
Arc<T> salt okunur verinin thread'ler arasında paylaşılmasını sağlar; değiştirme gerekiyorsa içine Mutex/RwLock konur. Büyük bir veriyi kopyalamadan parçalara bölüp her parçayı ayrı bir thread'e vermek tipik bir kullanımdır:
let veri: Arc<Vec<u32>> = Arc::new((1..=9).collect());
let tutucular: Vec<_> = (0..3)
.map(|i| {
let v = Arc::clone(&veri);
thread::spawn(move || v[i * 3..i * 3 + 3].iter().sum::<u32>())
})
.collect();Her thread yalnızca 8 baytlık bir işaretçi kopyası alır; vektörün kendisi tek bir kez bellekte durur.
Parçalara bölme
chunks(n) dilimi n'lik parçalara böler. Parça sayısını çekirdek sayısına göre seçmek iyi bir başlangıçtır: std::thread::available_parallelism().
let parca_boyu = veri.len().div_ceil(4);
for parca in veri.chunks(parca_boyu) {
// her parça bir thread'e
}Gerçek projelerde bu işi rayon crate'i tek satırda yapar: veri.par_iter().sum().
Uygulama Paralel parça toplamları
Arc<Vec<u32>> içinde 1'den 9'a kadar sayıları paylaş. Üç thread her biri üç elemanlık bir parçayı toplasın. Parça toplamlarını ve genel toplamı boşlukla yazdır.
Başlangıç kodu
use std::sync::Arc;
use std::thread;
fn main() {
// buraya yaz
}Örnek çözüm
use std::sync::Arc;
use std::thread;
fn main() {
let veri: Arc<Vec<u32>> = Arc::new((1..=9).collect());
let tutucular: Vec<_> = (0..3)
.map(|i| {
let v = Arc::clone(&veri);
thread::spawn(move || v[i * 3..i * 3 + 3].iter().sum::<u32>())
})
.collect();
let parcalar: Vec<u32> = tutucular.into_iter().map(|h| h.join().unwrap()).collect();
let toplam: u32 = parcalar.iter().sum();
println!("{:?} {}", parcalar, toplam);
}Beklenen çıktı
[6, 15, 24] 45
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Aynı işi kopyasız yapmanın <code>Arc</code> dışındaki yolu nedir?
- thread::scope ile dilimleri ödünç vermek Doğru cevap
- static mut
- Rc
- clone
Açıklama: Veri yalnızca bu hesap süresince gerekiyorsa scope daha basittir; thread'ler fonksiyondan uzun yaşayacaksa Arc gerekir.
2 İşaretçiyi kopyala
let v = Arc::____(&veri);
thread::spawn(move || v.len());
let v = Arc::clone(&veri);
thread::spawn(move || v.len());
Açıklama: Arc::clone yalnızca sayacı artırır, veriyi kopyalamaz.
3 Araç ve kullanım
| Kavram | Anlamı |
|---|---|
Arc<T> |
Salt okunur paylaşım |
Arc<Mutex<T>> |
Değiştirilebilir paylaşım |
thread::scope |
Geçici ödünç |
rayon |
Paralel yineleyici |