用资源约束限制 Ray 并发任务数量:基于 memory 与 num_cpus 的 OOM 防护实践
用资源约束限制 Ray 并发任务数量基于 memory 与 num_cpus 的 OOM 防护实践【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray导读在 Ray 中任务的并行度由调度器根据资源可用性自动决定。但当任务需要加载大量数据到堆内存时默认的并发策略可能让节点内存被迅速耗尽并触发 OOM。本文介绍 Ray 官方核心模式「使用资源Resources限制并发运行任务数」通过调整任务的memory、num_cpus等资源需求主动控制单节点上同时运行的任务与 Actor 数量从根本上预防内存过载。读完本文你将掌握资源需求与调度准入的底层机制、无限制与有限制两种写法的对比以及 Actor、逻辑资源、自定义资源等边界场景的处理方法。模式概述为什么要限制并发运行的任务数在 Ray 中任务Task和Actor的并发度并非无约束的调度器会依据每个节点可用的资源数量来决定能同时运行多少个任务。默认情况下Ray 的每个任务默认请求1 个 CPU资源Ray 的每个 Actor 默认请求0 个 CPU资源调度时 1 个、运行时 0 个详见后文。因此调度器会把任务的并发数限制在可用 CPU 数量以内而 Actor 的并发数则几乎是无限的。对于单个任务使用超过 1 个 CPU例如通过多线程的场景并发任务之间可能因竞争而出现性能下降但一般不会引发严重问题。真正危险的是内存如果任务或 Actor 使用的内存超过了它应有的份额多个并发实例叠加起来就可能让节点过载引发 OOM内存耗尽。针对这种情况本模式给出的解决方案非常直接——提高每个任务或 Actor 请求的资源量从而减少每个节点上并发运行的任务或 Actor 数量。这一做法之所以有效是因为 Ray 保证同一节点上所有并发运行的任务与 Actor 的资源需求之和不会超过该节点的总资源。这是 Ray 调度器在准入控制admission control环节强制保证的不变量也是本模式的原理基石。注意Actor 任务对于 Actor 上执行的任务actor tasks并发运行的 Actor 数量会直接限制可同时运行的 actor task 数量。也就是说想限制 actor task 的并发度先要限制 Actor 本身的并发度。典型使用场景数据处理负载的 OOM 防护本模式最典型的应用场景如下你有一个数据处理工作负载它使用 Ray 的远程函数remote functions 独立地处理每一个输入文件。由于每个任务都需要把输入数据加载进堆内存并完成处理同时运行的任务过多时很容易导致 OOM。在这个场景中每个任务都需要大量堆内存而 CPU 用量可能并不高。此时就可以用memory资源来限制并发运行的任务数使用num_cpus等其他资源也能达到同样的目的。需要特别强调的是与num_cpus类似memory资源需求是逻辑的。Ray 不会强制监控每个任务的实际物理内存占用也不会在任务实际内存超过声明值时干预或杀死任务。也就是说资源需求只影响调度准入真正的内存自律需要由任务自身保证——这是一个在使用本模式前必须理解的前提。代码示例无限制 vs 有限制完整的可运行示例位于仓库中的 limit_running_tasks.py下面对照展开。无限制版本16 个并发任务压垮 16G 内存import ray # 假设该 Ray 节点有 16 个 CPU 和 16G 内存。 ray.init() ray.remote def process(file): # 实际工作为读取文件并处理数据。 # 假设每个任务需要占用 2G 内存。 pass NUM_FILES 1000 result_refs [] for i in range(NUM_FILES): # 默认情况下process 任务使用 1 个 CPU 资源不请求其他资源。 # 这意味着 16 个任务可以并发运行 # 而 16 个任务总共需要 32G 内存远超节点 16G必然 OOM。 result_refs.append(process.remote(f{i}.csv)) ray.get(result_refs)在没有限制的版本中process任务只声明了默认的 1 CPU 资源没有声明任何内存需求。节点有 16 个 CPU所以调度器允许 16 个任务并发运行而每个任务实际需要 2G 内存16 个并发任务共需要 32G远超节点 16G 的内存容量最终会触发 OOM。有限制版本通过 memory 资源把并发数压到 8result_refs [] for i in range(NUM_FILES): # 现在每个任务声明使用 2G 内存资源 # 并发运行的任务数被限制为 8 个16G / 2G。 # 在这种场景下把 num_cpus 设为 2 也能达到同样的效果。 result_refs.append( process.options(memory2 * 1024 * 1024 * 1024).remote(f{i}.csv) ) ray.get(result_refs)关键改动只有一处通过process.options(memory2 * 1024 * 1024 * 1024)为每个任务显式声明2G 内存资源需求注意单位是字节2 * 1024 * 1024 * 1024即 2GiB。节点总内存为 16G因此调度器最多允许16G / 2G 8个任务并发运行8 个任务总共最多消耗 16G 内存恰好不会超过节点容量OOM 问题随之消除。代码注释中还给出了一个等价写法把num_cpus设为 2 也能达到同样的并发限制效果16 个 CPU / 2 CPU 8 个并发任务因为调度器只关心资源需求总和不超过节点资源这一约束而不在乎具体使用哪种资源。原理纵深Ray 资源需求与调度准入机制要深入理解本模式需要掌握 Ray 资源系统的基本模型详见文档 Resources。资源是逻辑的而非物理的Ray 中的资源是一个键值对键是资源名称值是浮点数数量。CPU、GPU、内存是 Ray 原生支持的预定义资源除此之外还支持自定义资源。关键的语义是Ray 资源是逻辑资源不必与物理资源一一对应。例如可以通过ray start --head --num-cpus0在物理上拥有 8 个 CPU 的机器上启动一个拥有 0 个逻辑 CPU 的 head 节点这样做主要是让调度器不在 head 节点上调度任务把资源留给 Ray 系统进程。逻辑资源的语义带来了几个重要推论资源需求不约束实际物理资源使用Ray 不会阻止一个num_cpus1的任务启动多线程并使用多个物理 CPU同样声明memory2G的任务若实际吃掉 4G 内存Ray 也不会干预。确保任务实际用量不超过声明值是开发者自己的责任。Ray 不做 CPU 隔离不会为某个任务预留物理 CPU 或做亲和性绑定线程调度交给操作系统必要时可用sched_setaffinity等系统 API 自行绑定。Ray 提供 GPU 隔离通过自动设置CUDA_VISIBLE_DEVICES环境变量以可见设备的形式隔离 GPU详见 Accelerators。此外若为任务/Actor 设置了num_cpusRay 会为其设置OMP_NUM_THREADSnum_cpus环境变量未指定时则设为 1以避免多 worker 场景下 OpenMP 线程争抢。这一点在使用多线程线性代数库numpy、PyTorch、TensorFlow时值得留意。节点资源的默认配置规则在不做任何显式配置时Ray 会按以下规则自动确定每个节点的逻辑资源量逻辑 CPU 数num_cpus等于机器/容器的 CPU 数逻辑 GPU 数num_gpus等于机器/容器的 GPU 数内存memory等于 Ray 运行时启动时可用内存的70%对象存储内存object_store_memory等于可用内存的 30%注意对象存储内存不是逻辑资源不能用于调度。因此本文示例中节点有 16G 内存对应的实际逻辑memory资源量约为 11.2G16G × 70%读者在自己环境中复现时应结合实际节点内存与配置计算并发上限。注意 Ray不允许在节点启动后动态更新资源容量。调度保证并发资源需求之和不超过节点总量文档 Resources 中明确给出了任务与 Actor 资源需求对调度并发度的影响同一节点上所有并发执行的任务与 Actor 的逻辑资源需求之和不能超过该节点的总逻辑资源。这正是本模式的全部依据把每个任务的内存需求声明得越大能被同时调度到该节点上的任务就越少。文档还专门把利用这一性质限制并发运行任务、规避 OOM的做法链接到了本文讲解的模式即core-patterns-limit-running-tasks说明这是官方推荐的标准实践。用 options() 与 ray.remote() 声明资源需求除了示例中的process.options(memory...)还有多种声明资源需求的方式在装饰器中声明ray.remote(num_cpus2, memory2 * 1024 * 1024 * 1024)在调用时声明process.options(num_cpus2, memory...)使用自定义资源process.options(resources{special_hardware: 1})。Java 与 C 也支持等价写法例如 C 中为ray::Task(MyFunction).SetResource(CPU, 1.0)、ray::Actor(CreateCounter).SetResource(GPU, 1.0)。分数资源需求Ray 支持分数资源需求。例如任务/ Actor 是 IO 密集型、CPU 占用很低时可以指定num_cpus0.5甚至num_cpus0。分数资源需求的精度为 0.0001应避免使用超出该精度的浮点数。另需注意GPU、TPU、neuron_cores 资源需求若大于 1必须为整数例如num_gpus1.5是非法值。Actor 场景与默认值陷阱文档 Actors 与 Resources 中明确指出默认情况下Ray 任务使用 1 个逻辑 CPU 资源Actor 在调度时使用 1 个逻辑 CPU在运行时使用 0 个逻辑 CPU。这意味着默认情况下 Actor 无法被调度到 0 CPU 节点上但在任何非 0 CPU 节点上都可以无限量地运行这一默认行为是历史原因造成的。因此想限制 Actor 的并发数必须显式设置num_cpus例如ray.remote(num_cpus1)否则并发 Actor 数量不受 CPU 约束也就无法借助本模式控流若显式声明了资源需求这些资源在调度时和运行时都会被要求满足对于 actor task限制 Actor 本身的并发数即是限制其任务的并发数本模式开头 note 的内容。与其他限流模式的区分limit-pending-tasksRay 的核心模式索引中还有一个容易混淆的模式「使用 ray.wait 限制 pending 任务数」。两者的分工如下本文模式limit running tasks通过调整每个任务的资源需求控制有多少任务可以同时运行属于调度层面的资源准入控制是本模式推荐的修改并发运行数的标准方法limit-pending-tasks 模式通过ray.wait()施加背压backpressure控制有多少任务处于在途in-flight/ 排队pending状态防止无限提交任务导致 pending 队列无限增长。它主要用于限制同时飞行中的任务数虽然也可用于限制并发运行数但不推荐因为会影响调度性能。两者的适用场景也不同如果一次性提交有限数量的任务每个任务在队列中仅占用少量内存做簿记通常不会出问题真正危险的是源源不断提交任务的无限流。当面对无限任务流时优先考虑ray.wait()背压而当目标是精确控制并发运行数时则应回归本文的资源需求方案。小结与最佳实践清单总结本模式的实践要点默认并发任务默认 1 CPUActor 默认运行时 0 CPUCPU 限制了任务并发但 Actor 并发近乎无限。OOM 根因任务/Actor 实际内存用量超过其资源份额多实例叠加导致节点内存耗尽。核心手段通过task.options(memory...)、num_cpus或自定义资源提高单任务资源声明利用节点上并发资源需求之和 ≤ 节点总资源的调度不变量压降并发数。逻辑资源语义memory与num_cpus都是逻辑资源Ray 不强制监控实际物理用量任务自身需自律。节点资源默认值内存逻辑资源默认是可用内存的 70%复现示例时需按实际节点配置计算并发上限。Actor 需显式设num_cpus否则并发不受控actor task 的并发由 Actor 并发决定。区分两种限流控制运行中任务数用本模式资源需求控制排队中任务数用 ray.wait 背压模式。通过为任务声明合理的内存或 CPU资源需求你可以在不改动任何业务逻辑的前提下用一行options()调用为数据密集型负载建立可靠的 OOM 防线。【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

AI内存与存储成本飙升:算力税与物理极限的破局之道

AI内存与存储成本飙升:算力税与物理极限的破局之道

这两年做AI相关项目的朋友应该都有同一个感受:内存和存储的成本,上涨速度比模型本身的推理能力还快。去年一台推理服务器用256GB内存还能轻松扛住测试流量,今年同样的负载直接把我内存条吃到报警,交换分区疯狂闪烁,服务…

2026/9/23 10:36:10 阅读更多 →
OpenAI Agents API实战:云端Agent循环、工具调用与自动化流程重构

OpenAI Agents API实战:云端Agent循环、工具调用与自动化流程重构

OpenAI 的 Agents API 现在正式开放了,我第一时间拿它把手头一个本来要跑三四个服务的自动化流程整个重写了一遍。以前想做一个能自己规划、自己调工具、自己干活的 Agent,要么自己维护一套 agent loop 调度逻辑,要么在本地折腾一堆编排框架&…

2026/9/21 17:40:15 阅读更多 →
Tinycast:原生 macOS 启动器的技术解析与实战指南——零依赖、SwiftUI 渲染 Raycast 扩展

Tinycast:原生 macOS 启动器的技术解析与实战指南——零依赖、SwiftUI 渲染 Raycast 扩展

Tinycast:原生 macOS 启动器的技术解析与实战指南——零依赖、SwiftUI 渲染 Raycast 扩展 【免费下载链接】tinycast Tinycast — a tiny, fully native macOS launcher, hotkeys, and clipboard history. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny…

2026/9/21 12:46:21 阅读更多 →

最新新闻

默纳克11KW底座原理图详解:从主回路到IGBT驱动与故障检修

默纳克11KW底座原理图详解:从主回路到IGBT驱动与故障检修

简介:汇川默纳克十一千瓦底座原理图是一份专供电路板维修使用的PDF电路图,面向变频器、电梯驱动及伺服控制设备的维修与技术支持人员,用于理解十一千瓦电机驱动系统中各电气组件和连接方式。图中详细标注了电容、电阻、二极管、晶体管、电感、…

2026/9/23 15:01:29 阅读更多 →
Python+MediaPipe+OpenCV手势识别课设:从关键点检测到音乐播放与鼠标控制

Python+MediaPipe+OpenCV手势识别课设:从关键点检测到音乐播放与鼠标控制

简介:这是一套面向高校计算机及相关专业学生的手势识别系统开发成果,适用于课程设计、期末大作业与毕业项目等实践环节,也可作为个人提升计算机视觉技能的实战训练材料。项目以Python为开发语言,结合MediaPipe与OpenCV构建&#x…

2026/9/23 15:01:29 阅读更多 →
三菱plc编程一文搞懂:从配置卡顿到稳定运行

三菱plc编程一文搞懂:从配置卡顿到稳定运行

三菱plc编程一文搞懂:从配置卡顿到稳定运行 刚打开GX Works2,是不是感觉CPU占用率瞬间飙满?导入一个旧项目,进度条卡在99%半天不动,鼠标指针都转圈了?这种 配置环境就卡半天…

2026/9/23 15:01:29 阅读更多 →
雷长喜入门到精通:3个致命坑让你从0到1少走5年弯路

雷长喜入门到精通:3个致命坑让你从0到1少走5年弯路

雷长喜入门到精通:3个致命坑让你从0到1少走5年弯路 刚毕业那会儿,我盯着屏幕上的 Hello World 发呆,语法书翻烂了,变量类型背得滚瓜烂熟,可一旦要动手搭个完整项目,脑子立马一片空白。这种“学会语法却不知怎么搭项目”的断崖式落差,…

2026/9/23 15:01:28 阅读更多 →
Nginx UI 重置初始管理员密码:reset-password 命令完整指南

Nginx UI 重置初始管理员密码:reset-password 命令完整指南

后端前端运维MCP 服务 【免费下载链接】nginx-ui Yet another WebUI for Nginx 项目地址: https://gitcode.com/gh_mirrors/ngi/nginx-ui 点击查看 免费下载 reset-password 是 Nginx UI 提供的官方命令行工具,用于在忘记初始管理员密码或初始账户被禁用…

2026/9/23 15:01:28 阅读更多 →
退款率怎么算:3个致命坑点与避坑指南

退款率怎么算:3个致命坑点与避坑指南

退款率怎么算:3个致命坑点与避坑指南 上周参加某大厂后端面试,二面官指着白板问:“你们系统的退款率是怎么算的?分母到底包不包含已取消的订单?”我愣了三秒,脑子里全是 COUNT(1)…

2026/9/23 15:00:27 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →