每週一庫 Rayon 資料平行計算庫

2021-10-04 04:57:48 字數 2961 閱讀 5506

rayon 是乙個rust的資料平行計算庫。它非常輕巧,可以輕鬆地將順序計算轉換為平行計算。同時保證不會有資料爭用情況出現。

使用rayon,可以輕鬆地將順序迭代器轉換為並行迭代器:通常,只需將您的foo.iter()呼叫更改為foo.par_iter(),其餘則由rayon完成:

use rayon::prelude::*;

fn sum_of_squares(input: &[i32]) -> i32

並行迭代器負責確定如何將資料劃分為任務;它會動態適應以達到最佳效能。如果你需要更大的靈活性,那麼rayon還提供了joinscope函式,允許使用者自己建立並行任務。為了獲得更多控制,還可以建立自定義執行緒池,而不是使用rayon的預設全域性執行緒池。

通常大家可能覺得並行執行會產生各種瘋狂的錯誤。不用緊張,rayon的api均保證無資料爭用情況發生,通常可以排除大多數並行錯誤(儘管不是全部)。換句話說,只要**通過編譯,它通常會執行與非並**況下相同的操作。

對於大多數情況,使用並行迭代器產生可以保證結果與順序迭代器結果相同。不過需要特別注意的是:如果您的迭代器有***(例如,通過rust通道將方法傳送到其他執行緒,或者磁碟寫入),這些***可能會以不同的順序發生。還要注意,在某些情況下,並行迭代器提供了具有更高效能的順序迭代器方法的替代版本。

[dependencies]

rayon = "1.1"

要使用並行迭代器api,特定的特徵必須被提前引用。引用這些特徵最簡單方法是使用rayon prelude。在每個要使用並行迭代器api的模組中,只需新增:

use rayon::prelude::*;
rayon 需要rustc 1.31.0及以上版本.

想要了解rayon的實際使用方法,請檢視rayon-demo目錄,其中包括使用rayon的許多**演示。例如,執行此命令以獲得nbody模擬的視覺化。要檢視使用rayon的效果,請按s進行順序執行,按p進行並行執行。

> cd rayon-demo

> cargo run --release -- nbody visualize

> cd rayon-demo

> cargo run --release -- --help

使用迭代器風格的介面編寫並行程式所需的特徵

除非你需要命名一種迭代器型別,否則幾乎不需要直接與此模組進行互動。

並行迭代器使編寫類似迭代器的並行執行鏈變得容易:通常,您要做的就是將第乙個.iter()(或iter_mut(),into_iter(), 等) 方法轉換為par_iter()(或par_iter_mut(),into_par_iter(), 等)。例如,要計算整數序列的平方和,可以這樣寫:

use rayon::prelude::*;

fn sum_of_squares(input: &[i32]) -> i32

或者,要遞增切片中的每個整數,可以這樣寫:

use rayon::prelude::*;

fn increment_all(input: &mut [i32])

要使用並行迭代器,首先通過在你的模組中新增use rayon::prelude::*來匯入特徵。然後,您可以呼叫par_iterpar_iter_mutinto_par_iter來獲取並行迭代器。像常規迭代器一樣,並行迭代器的工作方式是先構造乙個計算,然後執行。

pub fn join(oper_a: a, oper_b: b) -> (ra, rb) where

a: fnonce() -> ra + send,

b: fnonce() -> rb + send,

ra: send,

rb: send,

進行兩個閉包,盡可能的以並行的方式執行。並從這些閉包中返回一對結果。

從概念上講,呼叫join()類似於生成兩個執行緒,每個執行緒執行其中乙個閉包。但是,實現方式卻大不相同,並且產生的額外開銷非常低。我們使用的底層技術稱為「工作竊取」:rayon執行時使用固定的工作執行緒池,並嘗試僅在有空閒cpu處理時並行執行**。

當從執行緒池外部呼叫join時,當閉包在池中執行時,呼叫執行緒將阻塞。當在池中呼叫join時,呼叫執行緒仍會積極參與執行緒池。它將從在當前執行緒上執行閉包a開始。在執行的同時,它會通告其他執行緒閉包b為可被執行狀態。一旦閉包a完成,當前執行緒將嘗試執行閉包b。但是,如果封包b被"竊取",那麼它將在等待"竊取執行緒"完全執行封包b的同時尋找其他工作。(這是典型的工作竊取策略)。

let mut v = vec![5, 1, 8, 22, 0, 44];

quick_sort(&mut v);

assert_eq!(v, vec![0, 1, 5, 8, 22, 44]);

fn quick_sort(v: &mut [t])

}// 分割槽會將分界值左側所有的元素重新排列到切片的第一部分中

// (分界值被任意選取為切片中的最後乙個元素)

// 然後返回分界值的索引

fn partition(v: &mut [t]) -> usize

}v.swap(i, pivot);

i}

這次的每週一庫就到這裡。大家保重身體!keep coding!

平行計算 一 OpenMP

openmp是一種用於共享記憶體並行系統的多執行緒庫,其支援c c fortran,並且目前大多數常用編譯器,如vs內建編譯器 gcc icc等都提供了openmp的相關支援,以gcc為例編譯時只需要新增 fopenmp選項即可完成openmp 的編譯。openmp中包含了一套編譯器偽指令 執行時函...

大資料平行計算利器之MPI OpenMP

影象連通域標記演算法是從一幅柵格影象 通常為二值影象 中,將互相鄰接 4鄰接或8鄰接 的具有非背景值的畫素集合提取出來,為不同的連通域填入數字標記,並且統計連通域的數目。通過對柵格影象中進行連通域標記,可用於靜態地分析各連通域斑塊的分布,或動態地分析這些斑塊隨時間的集聚或離散,是影象處理非常基礎的演...

Rust每週一庫 hyper 底層http庫

現在說到寫應用,網路框架肯定是必不可少的。今天就給大家簡單介紹一下hyper。hyper是乙個偏底層的http庫,支援http 1和http 2,支援非同步rust,並且同時提供了服務端和客戶端的api支援。很多同學可能覺得既然hyper是個偏底層的框架,那是不是就不需要去了解了呢?首先很多上層的框...