ray 依赖分发

c 复制代码
如果你问的是 **Ray(Python 分布式计算框架)里的代码怎么发到 worker 节点执行**,可以分成两层理解:

## 1. `@ray.remote` 函数/Actor 本身怎么分发?

典型代码:

```python
import ray

ray.init(address="auto")

@ray.remote
def f(x):
    return x + 1

ref = f.remote(1)
print(ray.get(ref))

Ray 的大致流程是:

  1. Driver 进程里定义 @ray.remote 函数或 Actor。
  2. 第一次调用 .remote() 时,Ray 会把这个函数/类序列化。
  3. Ray 把序列化后的函数/类定义放到集群的 GCS / internal KV 里。
  4. 被调度到某个节点上的 worker 通过函数描述符拿到这段序列化代码。
  5. worker 反序列化后执行任务。

Ray 官方的 task lifecycle 文档里说明,RemoteFunction 会把底层函数 pickle 成字节,并存到 GCS key-value store,远端 executor 再取出、反序列化并执行。[1](#1)

Ray 的序列化基于 Pickle protocol 5,并借助 cloudpickle 支持 lambda、嵌套函数、动态类等 Python 对象。[2](#2)

2. 你的项目代码、依赖包怎么分发?

这是更容易踩坑的地方。

Ray 不会默认把你本地整个项目目录自动同步到所有节点@ray.remote 函数本身可以被序列化,但它里面 import 的模块、配置文件、模型文件、依赖库等,worker 节点也必须能访问。

通常有几种方式:


方式 A:用 runtime_env={"working_dir": ...} 分发项目目录

例如:

python 复制代码
ray.init(
    address="auto",
    runtime_env={
        "working_dir": ".",
        "pip": ["numpy", "pandas"]
    }
)

含义是:

  • 把当前目录作为运行目录分发到 worker;
  • worker 执行 task/actor 时可以 import 这个目录里的代码;
  • pip 字段用于安装 Python 依赖。

Ray 官方文档里 working_dir 被描述为本地路径或远程 URI,Ray 会把它解包到每个 task/actor 的工作目录中。[3](#3)


方式 B:用 runtime_env={"py_modules": [...]} 分发 Python 模块

例如:

python 复制代码
ray.init(
    address="auto",
    runtime_env={
        "py_modules": ["./my_package"]
    }
)

适合分发某个 Python package。Ray 会把这些模块加入 worker 的 PYTHONPATH。官方 API 文档说明,py_modules 可以是本地路径或远程 URI,Ray 会解包并插入 worker 的 PYTHONPATH[3](#3)


方式 C:把代码放到远程 URI

例如:

python 复制代码
ray.init(
    address="auto",
    runtime_env={
        "working_dir": "s3://my-bucket/my_project.zip"
    }
)

或者:

yaml 复制代码
runtime_env:
  working_dir: "https://github.com/xxx/project/archive/HEAD.zip"

这种方式更适合生产环境,因为不依赖 driver 本地机器上传代码。Ray Serve 文档也建议生产环境可以把代码打进镜像,或者用 runtime_env 指向远程存储中的代码。[4](#4)


方式 D:直接把代码和依赖打进镜像

生产环境最稳的方式通常是:

Dockerfile 复制代码
FROM rayproject/ray:latest

COPY . /app
WORKDIR /app

RUN pip install -r requirements.txt

然后整个 Ray 集群都用这个镜像启动。

优点:

  • 启动更稳定;
  • 不需要每次 job 提交都上传代码;
  • 依赖版本一致;
  • 更适合 Kubernetes / KubeRay / 生产部署。

3. 参数和返回值怎么分发?

函数代码是一回事,任务参数和返回值是另一回事。

例如:

python 复制代码
@ray.remote
def g(arr):
    return arr.sum()

调用:

python 复制代码
ref = g.remote(big_array)

Ray 会把参数序列化后放入对象存储。Ray 文档说明,Ray 使用 Plasma object store 在进程和节点之间高效传输对象;每个节点有自己的 object store,对象不会自动广播到所有节点,而是在其他 task/actor 请求时才传输。[2](#2)

所以:

  • 小参数会随 task 提交;
  • 大对象通常进入 Ray object store;
  • 跨节点需要时才拉取;
  • 返回值也是通过 ObjectRef 引用。

4. 一个直观总结

可以理解成:

text 复制代码
Driver
  |
  | 1. 序列化 @ray.remote 函数/Actor
  v
GCS / internal KV
  |
  | 2. worker 拉取函数定义
  v
Worker process

同时:

项目目录 / Python 模块 / pip 依赖
  |
  | 通过 runtime_env 或镜像分发
  v
Worker runtime environment

任务参数 / 返回值
  |
  | 通过 Ray object store 分发
  v
ObjectRef / Plasma store

5. 常见坑

坑 1:只定义了 remote 函数,但 worker 找不到本地模块

比如:

python 复制代码
from my_project.utils import helper

@ray.remote
def f(x):
    return helper(x)

如果 worker 节点没有 my_project,会报 ModuleNotFoundError

解决:

python 复制代码
ray.init(
    address="auto",
    runtime_env={"working_dir": "."}
)

或者把 my_project 安装成包:

python 复制代码
ray.init(
    address="auto",
    runtime_env={"pip": ["my_project==0.1.0"]}
)

坑 2:把大对象放进闭包

不要这样:

python 复制代码
big_model = load_model()

@ray.remote
def infer(x):
    return big_model(x)

这样 big_model 可能会跟函数一起被序列化,造成巨大开销。

更好的方式:

python 复制代码
model_ref = ray.put(load_model())

@ray.remote
def infer(model, x):
    return model(x)

ref = infer.remote(model_ref, data)

或者用 Actor 持有模型:

python 复制代码
@ray.remote
class ModelWorker:
    def __init__(self):
        self.model = load_model()

    def infer(self, x):
        return self.model(x)

坑 3:开发环境和生产环境混用

开发时可以用:

python 复制代码
runtime_env={"working_dir": "."}

生产时更推荐:

text 复制代码
Docker image + fixed requirements.txt / lockfile

这样可复现性更好。


简短结论

Ray 的代码分发可以概括为:

  1. @ray.remote 函数/Actor:Ray 用 pickle/cloudpickle 序列化后放到 GCS,worker 拉取后执行。
  2. 项目源码:不会默认全量同步,需要用 runtime_env["working_dir"]runtime_env["py_modules"]、远程 zip URI,或打进 Docker 镜像。
  3. Python 依赖:通过 runtime_env["pip"]condauv,或镜像安装。
  4. 参数和返回值:通过 Ray object store / ObjectRef 分发,不是代码分发。
复制代码

  1. Ray Task Lifecycle - official docs ↩︎

  2. Ray Serialization - official docs ↩︎ ↩︎

  3. ray.runtime_env.RuntimeEnv - official API docs ↩︎ ↩︎

  4. Ray Serve Handling Dependencies - official docs ↩︎

相关推荐
lbb 小魔仙1 小时前
Ollama 本地部署大模型 + Python API 集成开发完整教程(2026最新版,含 GPU 加速配置)
开发语言·python
DanCheng-studio2 小时前
毕设分享 深度学习遮挡下的人脸识别(源码+论文)
python·毕业设计·毕设
小妖同学学AI2 小时前
告别手动盯盘!开源框架Freqtrade,教你用Python打造“永不下班”的AI交易员
人工智能·python·开源
xxjj998a2 小时前
PHP vs Go vs Python:三大语言终极对比
python·golang·php
财经资讯数据_灵砚智能2 小时前
基于全球经济类多源新闻的NLP情感分析与数据可视化(日间)2026年5月5日
人工智能·python·信息可视化·自然语言处理·ai编程
wuyikeer2 小时前
Java进阶——IO 流
java·开发语言·python
lbb 小魔仙2 小时前
Ubuntu 22.04 + Windows 本地部署 AI 大模型完全指南:Ollama + Python 调用实战(附国内加速配置)
人工智能·windows·python·ubuntu
IT老兵20252 小时前
nvidia nemo-toolkit框架应用问题汇总
人工智能·python·机器学习·nemo
la_vie_est_belle2 小时前
Pygame Studio——用Python自制的一款可视化游戏编辑器
python·游戏·编辑器·游戏引擎·pygame·pyside6·pygame-ce