Files
FastDeploy/docs/zh/features/weight_update.md
T
jackyYang6 05f2d95729 [RL] Adapt async rollout checkpoint update flow (#7042)
* update checkpoint-transfer flow and control update_weights params

* test: add update_weights route validation
2026-03-30 19:19:34 +08:00

304 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
[English](../../features/weight_update.md)
# 权重清除与更新
FastDeploy 支持面向 RL / RLHF Rollout 服务的动态权重清除、显存卸载和权重更新,主要用于解决以下两类问题:
- Rollout 引擎空闲时释放 GPU 显存;
- Trainer 产出新 checkpoint 后,推理服务在不重启进程的情况下切换到新权重。
本文档介绍 FastDeploy 当前支持的权重控制接口、各接口的语义,以及它们在 RLHF 训练中的典型用法。
## 前置条件
在 RLHF 场景下,FastDeploy 主要通过在线服务模式提供该能力。启动服务时,需要开启动态权重加载:
```bash
python -m fastdeploy.entrypoints.openai.api_server \
--model /path/to/model \
--dynamic-load-weight \
--load-strategy ipc_snapshot
```
`--dynamic-load-weight` 用于开启动态权重控制能力,`--load-strategy` 用于指定具体的权重更新方式。当前支持的更新模式如下:
| 模式 | `load_strategy` | 典型场景 | 说明 |
| --- | --- | --- | --- |
| CUDA IPC | `ipc` | 训练进程与推理进程同机,直接共享实时张量 | 更新来源是训练侧产出的 IPC 元信息。 |
| IPC 快照 | `ipc_snapshot` | Rollout 从训练侧产出的权重快照文件重载 | 当前仓库里的 RL rollout 示例主要使用该模式。 |
| RDMA / rsync | `rsync` | Trainer 发布新版本,Rollout 远端拉取 | `POST /v1/update_weights` 是这一模式的显式接口。 |
## 接口说明
### 旧版接口
在 FastDeploy <= 2.5 版本中,主要提供以下简化接口,保留给旧版 RL 控制流使用。
| 接口 | 方法 | 含义 | 可用条件 |
| --- | --- | --- | --- |
| `/clear_load_weight` | `GET` | 清除或卸载当前已加载权重 | 需要 `dynamic_load_weight=True` |
| `/update_model_weight` | `GET` | 在清除/卸载后重新加载权重 | 需要 `dynamic_load_weight=True` |
### V1 新版接口
在 FastDeploy >= 2.6 版本中,底层控制信号通信链路经过优化,并引入了 V1 控制接口。相较于旧版接口,V1 接口在通信与执行链路上更稳定,语义更清晰,同时提供了更灵活的控制方式,包括以下接口:
| 接口 | 方法 | 请求参数 | 语义 |
| --- | --- | --- | --- |
| `/v1/pause` | `POST` | 无 | 暂停请求生成,中断 running/inflight 请求,重置调度器,并在开启 cache transfer 时暂停 cache transfer。 |
| `/v1/resume` | `POST` | 无 | 恢复请求生成和 cache transfer。 |
| `/v1/is_paused` | `GET` | 无 | 返回 `{"is_paused": bool}`。 |
| `/v1/sleep` | `POST` | `?tags=weight,kv_cache` | 卸载指定 GPU 内存对象。支持 `weight``kv_cache`;不传时默认同时处理两者。 |
| `/v1/wakeup` | `POST` | `?tags=weight,kv_cache` | 重新加载之前被卸载的权重和/或 KV Cache。成功后会自动 `resume`。 |
| `/v1/update_weights` | `POST` | JSON `{"version":"...", "verify_checksum": false}` | 通过 worker 控制链路原地刷新模型权重。该接口主要面向 `load_strategy=rsync` 的远端版本更新。 |
### 兼容性说明
底层通信链路的优化同样适用于旧版接口。通过设置环境变量 `FD_ENABLE_V1_UPDATE_WEIGHTS=1`,可以将旧版接口切换到新的控制链路,在保留兼容接口形式的同时,获得更明确的执行路径和更好的可观测性。
- `FD_ENABLE_V1_UPDATE_WEIGHTS=0`:走旧版基于共享内存的控制链路。
- `FD_ENABLE_V1_UPDATE_WEIGHTS=1``/clear_load_weight` 底层等价于执行 `/v1/sleep``/update_model_weight` 底层等价于执行 `/v1/wakeup`。对应的 pause/resume 动作分别由 `sleep``wakeup` 内部处理。
**注意**:无论是否设置 V1 环境变量,旧版接口都不是 RLHF 场景下推荐的标准使用方式,后续版本中也可能逐步废弃。建议优先使用 `/v1/*` 控制接口。
## 各接口语义
### `/v1/pause`
`/v1/pause` 是变更模型状态前的安全边界。
它会执行以下动作:
- 停止新请求生成;
- 中断当前 running 和 inflight 请求;
- 重置调度器状态;
- 在启用多级缓存或 KV Cache 存储时暂停 cache 传输。
如果需要在每一轮 rollout 与下一轮训练之间建立清晰的切换边界,建议先调用该接口。
### `/v1/sleep`
`/v1/sleep` 用于从 GPU 显存中卸载指定的运行时状态。
当前支持的 `tags`
- `weight`:清除设备上的模型权重;如果开启了相关配置,还可能一并释放通信组和 DeepEP buffer。
- `kv_cache`:清除 KV Cache;如果投机解码采用 MTP,还会同步清理 MTP cache。
如果不传 `tags` 参数,FastDeploy 默认等价于:
```bash
/v1/sleep?tags=weight,kv_cache
```
当前实现中,`sleep` 会自动先执行一次 `pause`。但新的接入方不应长期依赖这一隐式行为。
### `/v1/wakeup`
`/v1/wakeup` 用于恢复通过 `/v1/sleep` 卸载的状态。
根据 `tags` 和运行配置,FastDeploy 可能执行:
- 重建通信组;
- 重建 DeepEP buffer
- 从当前配置的数据源重新加载模型权重;
- 重建 KV Cache
- 重新捕获 CUDA Graph。
`wakeup` 成功后,FastDeploy 会自动调用一次 `resume`
### `/v1/update_weights`
`/v1/update_weights` 用于在不卸载模型权重显存占用的情况下,直接刷新模型参数。
当前支持的请求字段:
- `version`:可选字符串,用于指定目标 checkpoint 版本。
- `verify_checksum`:可选布尔值;默认为 `false`。设置为 `true` 时,会在权重同步过程中校验数据完整性。
关键语义:
- 调用前引擎必须已经处于暂停状态,否则请求会失败;
- 实际更新动作只在 worker 侧执行;
- 该接口主要用于显式权重刷新,尤其是 `rsync` 路径;
- 它不会自动执行 `resume`
推荐调用顺序:
1. `POST /v1/pause`
2. `POST /v1/update_weights`
3. `POST /v1/resume`
如果除更新权重外,还希望在 rollout 轮次之间回收 GPU 显存,则更适合使用 `sleep` / `wakeup` 组合。
## 请求示例
### 基础接口
暂停引擎:
```bash
curl -X POST http://127.0.0.1:8000/v1/pause
```
恢复引擎:
```bash
curl -X POST http://127.0.0.1:8000/v1/resume
```
### Sleep / Wakeup 接口
**卸载权重和 KV Cache**
```bash
# 同时卸载权重和 KV Cache
curl -X POST "http://127.0.0.1:8000/v1/sleep?tags=weight,kv_cache"
# 只卸载权重
curl -X POST "http://127.0.0.1:8000/v1/sleep?tags=weight"
# 不传参数,默认同时卸载两者
curl -X POST "http://127.0.0.1:8000/v1/sleep"
```
**恢复权重和 KV Cache**
```bash
# 恢复权重和 KV Cache
curl -X POST "http://127.0.0.1:8000/v1/wakeup?tags=weight,kv_cache"
# 只恢复权重
curl -X POST "http://127.0.0.1:8000/v1/wakeup?tags=weight"
# 不传参数,默认同时恢复两者
curl -X POST "http://127.0.0.1:8000/v1/wakeup"
```
**注意**:当 `use_cudagraph=True` 时,必须先恢复 KV Cache 再恢复权重。这意味着调用 `/v1/wakeup` 时如果只包含 `weight` tag 而不包含 `kv_cache`,会报错。建议保持 sleep 和 wakeup 的 tags 参数一致。
### Update Weights 接口
切换到远端发布的新版本权重:
```bash
curl -X POST http://127.0.0.1:8000/v1/update_weights \
-H "Content-Type: application/json" \
-d '{
"version": "global_step_1200",
"verify_checksum": false
}'
```
## 在 RLHF 中如何使用
### 推荐的 Rollout 服务配置
在 RLHF 场景下,FastDeploy 的 Rollout 服务通常采用以下配置:
- `dynamic_load_weight=True`
- `load_strategy=ipc_snapshot`,适合本地快照式刷新;
-`load_strategy=rsync`,适合远端版本化刷新。
仓库中的 RL rollout 工具已经按该方式接入。典型写法如下:
```python
from fastdeploy.rl.rollout_config import RolloutModelConfig
from fastdeploy.rl.rollout_model import RolloutModel
rollout_config = RolloutModelConfig(
model_name_or_path=model_path,
tensor_parallel_size=ranks,
dynamic_load_weight=True,
load_strategy="ipc_snapshot",
)
rollout_model = RolloutModel(rollout_config)
```
### FastDeploy 对训练侧的支持
除服务接口外,FastDeploy 还提供以下两类 RLHF 训练侧对接能力:
- `RolloutModel.state_dict()`:暴露 rollout 侧的推理参数;
- `RolloutModel.get_name_mappings_to_training()`:暴露推理参数名到训练参数名的映射关系。
这两个接口可用于训练侧 checkpoint 与 rollout 侧权重布局对齐,尤其适用于推理态和训练态参数命名不完全一致的场景。
### RLHF 常见工作流
以下给出 RLHF 场景下几种常见调用方式。示例中假设服务地址为 `http://127.0.0.1:8000`
**工作流 1:显存卸载与恢复**
适用于 rollout 服务常驻,但需要在训练阶段前后释放并恢复显存的场景。推荐流程为 `(pause) -> sleep -> wakeup -> (resume)`,其中括号内步骤为可选。
```bash
# 可选:先显式暂停引擎,建立清晰的切换边界
curl -X POST http://127.0.0.1:8000/v1/pause
# 卸载权重和 KV Cache
curl -X POST "http://127.0.0.1:8000/v1/sleep?tags=weight,kv_cache"
# 训练完成后恢复权重和 KV Cache
curl -X POST "http://127.0.0.1:8000/v1/wakeup?tags=weight,kv_cache"
# 可选:如业务侧需要显式恢复,可手动调用
curl -X POST http://127.0.0.1:8000/v1/resume
```
**工作流 2:原地刷新到新 checkpoint**
适用于服务常驻、仅需要切换到新版本权重的场景。推荐流程为 `pause -> update_weights -> resume`
```bash
# 先暂停引擎
curl -X POST http://127.0.0.1:8000/v1/pause
# 原地刷新到新版本权重
curl -X POST http://127.0.0.1:8000/v1/update_weights \
-H "Content-Type: application/json" \
-d '{
"version": "global_step_1200",
"verify_checksum": false
}'
# 更新完成后恢复服务
curl -X POST http://127.0.0.1:8000/v1/resume
```
**工作流 3:兼容旧版接口**
旧版 RL 客户端仍可继续使用兼容接口,流程为 `clear_load_weight -> update_model_weight`
```bash
# 清除或卸载当前权重
curl -X GET http://127.0.0.1:8000/clear_load_weight
# 训练侧完成 checkpoint 更新后,重新加载权重
curl -X GET http://127.0.0.1:8000/update_model_weight
```
对于新的接入方,建议优先使用 `/v1/*` 接口,因为其控制链路更显式,日志排查和故障定位也更直接。
## 其他相关配置
### 通信组的销毁与重建
FastDeploy 支持通过 `--shutdown-comm-group-if-worker-idle``--no-shutdown-comm-group-if-worker-idle`,显式控制在卸载权重时是否同时销毁通信组。
保留通信组通常有助于提升权重清除和重新加载过程中的稳定性;相应地,代价是卸载权重后仍会保留更多显存占用,同时 `sleep` / `wakeup` 的执行时间也可能更长。
默认情况下:
- 在 EP 场景下,默认不销毁通信组;
- 在非 EP 场景下,默认销毁通信组。
### CPU 缓存的清除与重建
启用 `--swap-space` 后,可以通过以下环境变量控制在执行 `/v1/sleep` 时,是否同步清理 CPU 侧缓存,以降低训练阶段的内存压力。
默认情况下,FastDeploy 不会主动清理 CPU Cache。如需在 `sleep` 时一并清理,可设置:
```bash
export FD_ENABLE_SWAP_SPACE_CLEARING=1
```