理論上并行和語言并沒有什么關(guān)系,所以在理論上的并行方式,都可以嘗試用Rust來實現(xiàn)。本小節(jié)不會詳細(xì)全面地介紹具體的并行理論知識,只介紹用Rust如何來實現(xiàn)相關(guān)的并行模式。
Rust的一大特點是,可以保證“線程安全”。而且,沒有性能損失。更有意思的是,Rust編譯器實際上只有Send
Sync
等基本抽象,而對“線程” “鎖” “同步” 等基本的并行相關(guān)的概念一無所知,這些概念都是由庫實現(xiàn)的。這意味著Rust實現(xiàn)并行編程可以有比較好的擴(kuò)展性,可以很輕松地用庫來支持那些常見的并行編程模式。
下面,我們以一個例子來演示一下,Rust如何將線程安全/執(zhí)行高效/使用簡單結(jié)合起來的。
在圖形編程中,我們經(jīng)常要處理歸一化的問題: 即把一個范圍內(nèi)的值,轉(zhuǎn)換到范圍1內(nèi)的值。比如把一個顏色值255歸一后就是1。假設(shè)我們有一個表示顏色值的數(shù)組要進(jìn)行歸一,用非并行化的方式來處理非常簡單,可以自行嘗試。下面我們將采用并行化的方式來處理,把數(shù)組中的值同時分開給多個線程一起并行歸一化處理。
extern crate rayon;
use rayon::prelude::*;
fn main() {
let mut colors = [-20.0f32, 0.0, 20.0, 40.0,
80.0, 100.0, 150.0, 180.0, 200.0, 250.0, 300.0];
println!("original: {:?}", &colors);
colors.par_iter_mut().for_each(|color| {
let c : f32 = if *color < 0.0 {
0.0
} else if *color > 255.0 {
255.0
} else {
*color
};
*color = c / 255.0;
});
println!("transformed: {:?}", &colors);
}
運行結(jié)果:
original: [-20, 0, 20, 40, 80, 100, 150, 180, 200, 250, 300]
transformed: [0, 0, 0.078431375, 0.15686275, 0.3137255, 0.39215687, 0.5882353, 0.7058824, 0.78431374, 0.98039216, 1]
以上代碼是不是很簡單。調(diào)用par_iter_mut
獲得一個并行執(zhí)行的具有寫權(quán)限的迭代器,for_each
對每個元素執(zhí)行一個操作。僅此而已。
我們能這么輕松地完成這個任務(wù),原因是我們引入了 rayon 這個庫。它把所有的臟活累活都干完了,把清晰安全易用的接口暴露出來給了我們。Rust還可以完全以庫的形式,實現(xiàn)異步IO、協(xié)程等更加高階的并行程序開發(fā)模式。
為了更深入的加深對Rust并發(fā)編程的理解和實踐,還安排了一個挑戰(zhàn)任務(wù):實現(xiàn)一個Rust版本的MapReduce模式。值得你挑戰(zhàn)。