只有被@ray.remote修饰的函数才会被调度到远程worker执行;必须是纯函数、显式导入依赖、不直接remote类方法,而需修饰整个类后实例化。

Ray 能显著加速 CPU 密集型任务,但对简单 I/O 或小计算量任务反而拖慢;关键不在“用不用 Ray”,而在“哪些函数该 remote、怎么传参、资源怎么配”。
哪些函数必须加 @ray.remote?
只有被 @ray.remote 修饰的函数才会被调度到远程 worker 执行。普通函数调用仍走本地 Python 解释器,不触发分布式。
- 必须是纯函数(无副作用、不依赖全局状态),否则结果不可预测
- 不能引用未导入的模块——Ray worker 是独立进程,需在函数内显式
import - 类方法不能直接 remote;要 remote 类,得用
@ray.remote修饰整个类,再调用.remote()实例化
示例:
@ray.remote
def process_chunk(data):
import numpy as np # 必须在函数内 import
return np.sum(data ** 2)
<h1>错误写法:没加 @ray.remote,仍是本地同步执行</h1><p>def bad_func(x): return x + 1
</p>
ray.get() 和 ray.wait() 什么时候用?
ray.get() 是阻塞式取结果,适合你明确需要返回值且不介意等待;ray.wait() 是非阻塞式探针,适合批量提交后按完成顺序处理,避免空等。
- 连续调用多次
ray.get([obj1, obj2, ...])等价于等最慢那个,不是并行取 - 若想“谁先算完就先处理”,用
ray.wait(remaining_refs, num_returns=1)拿第一个完成的 ID,再ray.get()取值 - 忘记调用
ray.get()就永远拿不到结果——对象 ID 不是值本身
常见错误现象:ObjectRef(...) 被打印出来却没报错,其实是忘了 ray.get()。
CPU 资源不够时,num_cpus= 设多少才不排队?
Ray 默认每个 task 请求 1 个 CPU slot。如果集群总 CPU 数为 8,而你提交 10 个 @ray.remote(num_cpus=1) 任务,后 2 个会排队,直到有 slot 空闲。
- 小任务(如每次处理几百条记录)可设
num_cpus=0.1,提高并发密度 - 内存吃紧的任务,要同时加
memory=...,否则可能因 OOM 被杀而无提示 - 本地测试时,
ray.init(num_cpus=4)是起点;不指定则默认用os.cpu_count(),容易挤占本机交互响应
注意:num_cpus 是逻辑配额,不是硬绑定——它只影响调度排队,不隔离 CPU 核心。
为什么 ray.put() 和 ray.get() 配合大数组很慢?
因为 ray.put() 默认把对象序列化后存入共享内存(Plasma store),但大 NumPy 数组若未用 copy=False 或未预分配,会触发深拷贝+多次内存复制。
- 传大数组优先用
ray.put(arr, buffer_callback=...)或直接传路径(让 worker 自己加载) - 更稳的做法:把数据存在磁盘或对象存储(S3 / Redis),task 内只传路径或 key
-
ray.put()返回的是ObjectRef,不是数据本身;反复ray.get(ref)不重算,但每次仍走一次共享内存读取路径
容易被忽略的地方:Ray 的对象序列化(cloudpickle)对自定义类支持有限,含文件句柄、线程锁、CUDA 张量的对象无法跨进程传递——这类必须拆成纯数据+重建逻辑。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











