【Rust線程池】如何構建Rust線程池、Rayon線程池用法詳細解析

在這里插入圖片描述

?? 歡迎大家來到景天科技苑??

🎈🎈 養成好習慣,先贊后看哦~🎈🎈

🏆 作者簡介:景天科技苑
🏆《頭銜》:大廠架構師,華為云開發者社區專家博主,阿里云開發者社區專家博主,CSDN全棧領域優質創作者,掘金優秀博主,51CTO博客專家等。
🏆《博客》:Rust開發,Python全棧,Golang開發,云原生開發,PyQt5和Tkinter桌面開發,小程序開發,人工智能,js逆向,App逆向,網絡系統安全,數據分析,Django,fastapi,flask等框架,云原生K8S,linux,shell腳本等實操經驗,網站搭建,數據庫等分享。

所屬的專欄:Rust高性能并發編程
景天的主頁:景天科技苑

在這里插入圖片描述

文章目錄

  • Rust線程池
    • rayon 線程池
      • 一、Rayon核心API詳解
        • 1.1 常用方法
        • 1.2 常見并行組合子(Combinators)
        • 1.3 自定義并行任務
      • 二、Rayon線程池ThreadPoolBuilder
        • 1. new() 方法
        • 2. num_threads() 方法
        • 3. thread_name() 方法
        • 4. build() 方法
        • 5. build_global 方法
        • 6. 其他方法
        • 7. 它還提供了一些回調函數的設置
        • 9. 注意事項

Rust線程池

線程池是一種并發編程的設計模式,它由一組預先創建的線程組成,用于執行多個任務。
線程池的主要作用是在任務到達時,重用已創建的線程,避免頻繁地創建和銷毀線程,從而提高系統的性能和資源利用率。
線程池通常用于需要處理大量短期任務或并發請求的應用程序。

線程池的優勢包括:
? 減少線程創建和銷毀的開銷:線程的創建和銷毀是一項昂貴的操作,線程池通過重用線程減少了這些開銷,提高了系統的響應速度和效率。
? 控制并發度:線程池可以限制同時執行的線程數量,從而有效控制系統的并發度,避免資源耗盡和過度競爭。
? 任務調度和負載均衡:線程池使用任務隊列和調度算法來管理和分配任務,確保任務按照合理的方式分配給可用的線程,實現負載均衡和最優的資源利用。

rayon 線程池

Rayon 是 Rust 中的一個并行計算庫,它可以讓你更容易地編寫并行代碼,以充分利用多核處理器。
Rayon 提供了一種簡單的 API,允許你將迭代操作并行化,從而加速處理大規模數據集的能力。
除了這些核心功能外,它還提供構建線程池的能力。
rayon::ThreadPoolBuilder 是 Rayon 庫中的一個結構體,用于自定義和配置 Rayon線程池的行為。
線程池是 Rayon 的核心部分,它管理并行任務的執行。
通過使用ThreadPoolBuilder,你可以根據你的需求定制 Rayon 線程池的行為,以便更好地適應你的并行計算任務。
在創建線程池之后,你可以使用 Rayon 提供的方法來并行執行任務,利用多核處理器的性能優勢。

一、Rayon核心API詳解

Rayon最核心的API是并行迭代器(ParallelIterator),其中包含豐富的方法集。

1.1 常用方法

par_iter():創建并行迭代器(只讀)。
par_iter_mut():創建可變并行迭代器。
into_par_iter():消耗數據源,創建并行迭代器。
示例:

use rayon::prelude::*;fn main() {let mut nums = vec![10, 20, 30, 40];// 并行修改元素值nums.par_iter_mut().for_each(|x| *x += 1);println!("{:?}", nums);
}

在這里插入圖片描述

不能直接在 par_iter 中嵌套 par_iter,否則會阻塞或 panic。使用獨立線程池可以避免嵌套并行死鎖。

1.2 常見并行組合子(Combinators)

map():并行映射。
filter():并行過濾。
reduce():并行歸約,合并結果。
fold():類似reduce,但支持初始狀態和結果合并。
find_any() / find_first():并行查找元素。

示例(并行篩選與轉換):

use rayon::prelude::*;fn main() {let nums = (0..1_000_000).collect::<Vec<_>>();// 并行篩選出偶數并求平方let squares: Vec<_> = nums.par_iter().filter(|&&x| x % 2 == 0).map(|&x| x * x).collect();println!("篩選后元素個數:{}", squares.len());
}

這段代碼,報錯就是要計算的數據超過i32類型的最大值導致的
我們在創建squares的時候,類型Vec<_>,編譯器會默認為i32,計算的數據很大,迭代0到1000000,然后計算偶數的平方,超過i32最大值,導致報錯
在這里插入圖片描述

🚩 解決方案:
創建squares時,指定更大的數據類型:

use rayon::prelude::*;fn main() {let nums = (0..1_000_000).collect::<Vec<_>>();// 并行篩選出偶數并求平方//將squares指定更大的數據類型let squares: Vec<u128> = nums.par_iter().filter(|&&x| x % 2 == 0).map(|&x| x * x).collect();println!("篩選后元素個數:{}", squares.len());
}

在這里插入圖片描述

1.3 自定義并行任務

Rayon提供了更底層的接口,讓你可以手動并行執行任務。
1.3.1 join方法
執行兩個并行任務,等待任務完成后繼續執行。

use rayon::join;fn fib(n: usize) -> usize {if n < 2 {return n;}let (a, b) = join(|| fib(n - 1),|| fib(n - 2));a + b
}fn main() {let result = fib(20);println!("斐波那契數:{}", result);
}

在這里插入圖片描述

1.3.2 scope方法
并行執行多個互相獨立的任務,生命周期靈活控制。

use rayon::scope;fn main() {let mut a = 0;let mut b = 0;scope(|s| {s.spawn(|_| {a = expensive_compute_a();});s.spawn(|_| {b = expensive_compute_b();});});println!("結果:{}, {}", a, b);
}fn expensive_compute_a() -> i32 {100
}
fn expensive_compute_b() -> i32 {200
}

在這里插入圖片描述

二、Rayon線程池ThreadPoolBuilder

rayon::ThreadPoolBuilder 是 Rayon 庫中用于 自定義線程池配置 的結構體,適用于對并發行為有更精細控制需求的場景。
Rayon 默認使用一個全局線程池(rayon::spawn、par_iter 默認使用它),但在某些情況下,我們希望:
控制線程池線程數量;
設置線程名、線程棧大小;
使用多個獨立的線程池隔離并發任務;
嵌套 Rayon 調用時避免死鎖(多線程池互不干擾);
這時,就需要用到 ThreadPoolBuilder。

ThreadPoolBuilder 是以設計模式中的構建者模式設計的, 以下是一些ThreadPoolBuilder 的主要方法:

1. new() 方法

創建一個新的 ThreadPoolBuilder 實例

use rayon::ThreadPoolBuilder;
fn main() {let builder = ThreadPoolBuilder::new();
}
2. num_threads() 方法

設置線程池的線程數量。
你可以通過這個方法指定線程池中的線程數,以控制并行度。
默認情況下,Rayon 會根據 CPU 內核數量自動設置線程數。

use rayon::ThreadPoolBuilder;
fn main() {let builder = ThreadPoolBuilder::new().num_threads(4); //設置線程池中的線程數量為4
}
3. thread_name() 方法

為線程池中的線程設置一個名稱,這可以幫助你在調試時更容易識別線程。

use rayon::ThreadPoolBuilder;
fn main() {let builder = ThreadPoolBuilder::new().thread_name(|i| format!("worker-{}", i));
}

查看每次執行的線程名

use rayon::prelude::*;
use rayon::ThreadPoolBuilder;
use std::thread;fn main() {let pool = ThreadPoolBuilder::new().num_threads(4).thread_name(|i| format!("my-pool-{}", i)).build().unwrap();pool.install(|| {let v: Vec<_> = (0..1000).into_par_iter().map(|x| {// 獲取當前線程名let thread_thread = thread::current();let thread_name = thread_thread.name().unwrap_or("unknown");println!("元素 {} 由線程 {} 處理", x, thread_name);x * x}).collect();println!("結果: {:?}", &v[..10]);});
}

在這里插入圖片描述

4. build() 方法

通過 build 方法來創建線程池。
這個方法會將之前的配置應用于線程池并返回一個 rayon::ThreadPool 實例。

use rayon::ThreadPoolBuilder;
fn main() {let pool = ThreadPoolBuilder::new().num_threads(4).thread_name(|i| format!("worker-{}", i)).build().unwrap(); // 使用unwrap()來處理潛在的錯誤
}
5. build_global 方法

通過 build_global 方法創建一個全局的線程池
不推薦你主動調用這個方法初始化全局的線程池,使用默認的配置就好,記得全局的線程池只會初始化一次。多次調用會 panic

fn main() {rayon::ThreadPoolBuilder::new().num_threads(22).build_global().unwrap();
}
6. 其他方法

ThreadPoolBuilder 還提供了其他一些方法,用于配置線程池的行為,
如 stack_size() 用于設置線程棧的大小。
設置每個線程的棧大小(單位:字節):

let builder = rayon::ThreadPoolBuilder::new().stack_size(8 * 1024 * 1024); // 8MB

適用于遞歸深度大、調用棧復雜的程序。

7. 它還提供了一些回調函數的設置

start_handler() 用于設置線程啟動時的回調函數等。
線程啟動時調用的回調函數,可以用于初始化日志、TLS 等:

let builder = rayon::ThreadPoolBuilder::new().start_handler(|idx| {println!("線程 {} 啟動", idx);});

spawn_handler 實現定制化的函數來產生線程。
panic_handler 提供對panic 處理的回調函數。
exit_handler 提供線程退出時的回調。

let builder = rayon::ThreadPoolBuilder::new().exit_handler(|idx| {println!("線程 {} 退出", idx);});

下面這個例子演示了使用 rayon 線程池計算斐波那契數列:

//使用ranyon線程池計算斐波那契數列
fn fib(n: u128) -> u128 {if n == 0 {return 0;}if n == 1 {return 1;}let (a, b) = rayon::join(|| fib(n - 1),|| fib(n - 2));a + b
}fn rayon_threadpool() {let pool = rayon::ThreadPoolBuilder::new().num_threads(10).build().unwrap();pool.install(|| {let result = fib(20);println!("result = {}", result);});
}fn main() {rayon_threadpool();
}

在這里插入圖片描述

? rayon::ThreadPoolBuilder 用來創建一個線程池。設置使用 10 個線程
? pool.install() 在線程池中運行 fib
? rayon::join 用于并行執行兩個函數并等待它們的結果。它使得你可以同時執行兩個獨立的任務,然后等待它們都完成,以便將它們的結果合并到一起。
通過在 join 中傳入 fib 遞歸任務, 實現并行計算 fib 數列
與直接 spawn thread 相比, 使用 rayon 的線程池有以下優點:
? 線程可重用, 避免頻繁創建/銷毀線程的開銷
? 線程數可配置, 一般根據 CPU 核心數設置
? 避免大量線程造成資源競爭問題

9. 注意事項

build_global() 只能調用一次;多次調用會 panic;
自定義線程池的 .install() 不能跨線程池嵌套調用 .par_iter();
不建議將阻塞操作(如IO)放入線程池中執行,Rayon主要用于CPU密集型任務;
一旦線程池創建完成,線程數不可更改,需重新構建。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90509.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90509.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90509.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

CAN總線網絡的參數協同:從一致性要求到容差邊界

CAN總線網絡的參數協同&#xff1a;從一致性要求到容差邊界 一、引言&#xff1a;CAN總線的“隱形契約”二、CAN通信的核心參數&#xff1a;不止于波特率三、參數一致性的必要性&#xff1a;為何波特率相同仍會失敗&#xff1f;四、容差范圍的科學界定&#xff1a;從理論計算到…

Activity 啟動模式

如何指定 Activity 的啟動模式&#xff1f;在 AndroidMainfest.xml 中通過給 <activity> 標簽指定 android:lauchMode 來選擇啟動模式。4種啟動模式standard&#xff08;默認&#xff09;&#xff1a;每當啟動一個 Activity&#xff0c;都會創建一個新的實例壓入返回棧。…

7·22勝算云AI日報:OpenAI再擴容且與英國政府簽訂三年AI計劃、字節GR-3、微軟Culture計劃、國數局數據基地

OpenAI Oracle&#xff1a;4.5 GW「Stargate II」再擴容&#xff0c;AI 電力版圖重排 7 月 22 日&#xff0c;OpenAI 與 Oracle 聯合公布“Stargate II”計劃&#xff1a;雙方將在美國多地追加 4.5 GW 超算級電力與冷卻配套&#xff0c;使 Stargate 系列園區總規模躍升至 5 GW…

【優選算法】鏈表

目錄鏈表常用的技巧和操作1、常用技巧2、常用操作一、[兩數相加](https://leetcode.cn/problems/add-two-numbers/description/)二、[兩兩交換鏈表中的節點](https://leetcode.cn/problems/swap-nodes-in-pairs/description/)三、[重排鏈表](https://leetcode.cn/problems/reor…

制造業新突破:AR 培訓系統助力復雜操作輕松上手?

在制造業&#xff0c;生產設備復雜、操作流程繁瑣&#xff0c;新員工掌握操作技能不易。比如汽車制造企業的發動機裝配環節&#xff0c;涉及眾多精密零部件安裝&#xff0c;對安裝順序、位置精度要求嚴格&#xff0c;一點小失誤都可能影響發動機性能甚至引發質量問題。過去新員…

《計算機網絡》實驗報告八 加密、數字簽名與證書

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 3.1 對稱加密 3.2 散列函數 3.3 非對稱加密 3.4 數字簽名 3.5 證書 4、實驗結果與分析 4.1 對稱加密 4.2 散列函數 4.3 非對稱加密 4.4 數字簽名 4.5 證書 5、實驗小結 5.1 問題與解決辦法&#xff1a; 5.2 心得體…

MySQL(157)如何分析和優化存儲過程?

分析和優化存儲過程是數據庫性能優化的重要環節。通過對存儲過程進行分析和優化&#xff0c;可以提高數據庫操作的執行效率&#xff0c;減少資源消耗&#xff0c;改善系統整體性能。以下是詳細的步驟和代碼示例&#xff0c;介紹如何分析和優化 MySQL 存儲過程。 一、分析存儲過…

基于深度學習的胸部 X 光圖像肺炎分類系統(一)

本文先重點介紹了過采樣的原理是實現。 由于醫學數據相對缺乏&#xff0c;過采樣是解決數據問題的方法之一。 后續寫一篇搭建神經網絡的說明 目錄 概述 導入必要的庫 數據加載和預處理函數 處理樣本不均衡函數 構建改進的 CNN 模型函數 主函數 數據生成器generator&…

【PGCCC】在 Postgres 中構建復制安全的 LSM 樹

在原生 Postgres 實現中&#xff0c;全文搜索由B 樹或GIN&#xff08;廣義倒排索引&#xff09;結構支持。這些索引針對相對快速的查找進行了優化&#xff0c;但受限于 B 樹的寫入吞吐量。 當我們構建pg_searchPostgres 搜索和分析擴展時&#xff0c;我們的優先級有所不同。為了…

架構如鐘擺:在變與不變之間優雅平衡

在當今數字轉型浪潮中&#xff0c;企業在“快速創新”與“長期穩定”之間反復拉扯。是否應該重建所有架構以適應AI&#xff1f;又是否該死守傳統系統確保安全與合規&#xff1f;在The Open Group阿姆斯特丹峰會上&#xff0c;凱捷全球 CTO Ron Tolido 借用了一個極具畫面感的比…

LLM中的位置嵌入矩陣(Position Embedding Matrix)是什么

LLM中的位置嵌入矩陣(Position Embedding Matrix)是什么 在大語言模型(LLM)中,位置嵌入矩陣(Position Embedding Matrix) 是用來表示輸入序列中每個詞的位置信息的矩陣。它的核心作用是:讓模型能夠區分“相同詞在不同位置的語義差異”(比如“貓喜歡魚”中的“貓”和“…

國產DevOps平臺Gitee:如何重塑中國企業研發效能新格局

國產DevOps平臺Gitee&#xff1a;如何重塑中國企業研發效能新格局 在全球數字化轉型浪潮中&#xff0c;軟件研發效率已成為企業競爭力的核心指標。作為中國最大的代碼托管平臺&#xff0c;Gitee正通過其全棧式DevOps解決方案&#xff0c;助力中國企業突破研發效能瓶頸&#xff…

告別混亂!【Java Web】項目分層架構全指南:核心三層 + 關鍵輔助包詳解

目錄 1.前言 2.正文 2.1為什么要分層 2.2核心三層詳解 2.2.1Controller層&#xff08;表現層/API層&#xff09; 2.2.2Service層&#xff08;業務邏輯層&#xff09; 2.2.3DAO層&#xff08;持久層&#xff09; 2.3. 核心關系與數據流轉&#xff1a;分層架構的交互邏輯…

解決Docker Compose報錯

解決Docker Compose報錯&#xff1a;exec ./entrypoint.sh: no such file or directory在使用Docker Compose部署應用時&#xff0c;你是否遇到過exec ./entrypoint.sh: no such file or directory這個令人頭疼的錯誤&#xff1f;本文將深入分析錯誤原因并提供多種解決方案&…

【element plus】el-select,allow-create不需要點回車鍵

<el-selectv-model"row.expertName"filterableremoteallow-createdefault-first-optionreserve-keywordplaceholder"請輸入姓名":remote-method"remoteMethod":loading"loadingName"change"(val) > handleNameChange(row, …

RK3588 HDMI-RX 驅動、RGA 加速與 OpenCV GStreamer 支持完整指南

一、環境檢測與前置依賴 確認內核與 HDMI-RX 節點&#xff1a; uname -a # 輸出&#xff1a;6.1.0-1025-rockchip ...dmesg | grep -i hdmirx # 應能看到 hdmirx-controller 節點&#xff1a; # fdee0000.hdmirx-controller driver probe ok!如果僅出現&#xff1a; rockchi…

AS32A601芯片QSPI 調試技術解析與與實戰經驗分享

一、概述&#xff08;一&#xff09;QSPI 簡介QSPI&#xff08;Quad Serial Peripheral Interface&#xff09;是一種高速串行通信接口&#xff0c;在標準 SPI&#xff08;Serial Peripheral Interface&#xff09;的基礎上擴展至 4 條數據線&#xff08;Quad Mode&#xff09;…

TDengine 轉化函數 TO_TIMESTAMP 用戶手冊

TDengine TO_TIMESTAMP 函數用戶使用手冊 函數概述 TO_TIMESTAMP 是 TDengine 中的標量函數&#xff0c;用于將字符串按照指定格式轉換為時間戳。該函數在數據導入、時間格式轉換、以及處理各種時間字符串格式時非常有用。 語法 TO_TIMESTAMP(ts_str_literal, format_str_liter…

關于我司即將對商業間諜行為進行法律訴訟的通知

最后警告我司所屬社交媒體中所有友商間諜&#xff1a;請于2025年7月26日上午十點前&#xff0c;自行刪除我方好友&#xff0c;并停止通過欺詐行為&#xff08;包括但不限于冒充客戶等&#xff09;盜取我司商業秘密的行為。十點后&#xff0c;我司將開始進行逐一排查&#xff0c…

【打怪升級 - 03】YOLO11/YOLO12/YOLOv10/YOLOv8 完全指南:從理論到代碼實戰,新手入門必看教程

引言&#xff1a;為什么選擇 YOLO&#xff1f; 在目標檢測領域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;系列模型一直以其高效性和準確性備受關注。作為新版本&#xff0c;YOLO系列的新版本總能在前輩的基礎上進行了多項改進&#xff0c;包括更高的檢測精度…