在这里插入图片描述

✨✨ 欢迎大家来到景天科技苑✨✨

🎈🎈 养成好习惯,先赞后看哦~🎈🎈

🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,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;包括更高的检测精度…