news 2026/6/15 12:54:19

详尽记录:从环境配置到脚本执行的每一步

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
详尽记录:从环境配置到脚本执行的每一步

详尽记录:从环境配置到脚本执行的每一步

这是一篇完全基于真实工程实践的 verl 框架部署手记。不讲抽象概念,不堆技术术语,只记录从零开始、在一块老旧 Tesla P40 GPU 上把 verl 跑起来的全部细节——包括哪些命令必须按顺序执行、哪些文件要手动修改、哪些报错看似相似实则根源不同、哪些坑踩了三次才绕过去。如果你正面对一个“能跑但总崩”的 verl 环境,或者刚 clone 下来却卡在 import 阶段,这篇文章里的每一行命令、每一个路径、每一次替换,都是可直接复用的实操快照。


1. 为什么是 Tesla P40?又为什么非得跑 verl?

先说清楚前提:这不是一份面向生产集群的部署指南,而是一份单卡、低配、强约束下的可行性验证记录。硬件是 2016 年发布的 Tesla P40(24GB 显存,CUDA Compute Capability 6.1),操作系统是 Ubuntu 20.04,目标模型是 Qwen2.5-0.5B-Instruct(参数量约 5 亿),训练数据是 GSM8K(数学推理题集)。

选择它,不是因为推荐,而是因为现实——很多开发者手头没有 A100/H100,甚至没有 RTX 4090,只有一张被遗忘在服务器角落的老卡。而 verl 作为专为 LLM 后训练设计的 RL 框架,其价值恰恰在于让中小规模团队也能尝试 PPO、DPO 等高级对齐方法。所以本文不追求“最优性能”,只回答一个朴素问题:在资源受限条件下,verl 能不能动起来?怎么动?

答案是:能,但需要绕开三类硬性限制——CUDA 版本兼容性、数据类型支持边界、显存资源分配策略。下面所有步骤,都围绕这三点展开。


2. 环境配置:严格顺序不可跳过

官方文档默认假设你使用较新 GPU(如 A100)和 CUDA 12.x,但 Tesla P40 的硬件能力决定了我们必须回退到 CUDA 11.8 + cuDNN 8.9.7 这一组合。任何顺序错乱或版本混用,都会导致后续 import 失败或运行时崩溃。

2.1 基础依赖安装顺序表

步骤组件版本关键说明
1CUDA11.8必须用runfile安装,路径固定为/usr/local/cuda-11.8不可覆盖系统默认 cuda 软链接,否则 pyTorch 会加载错版本
2cuDNN8.9.7 for CUDA 11.x解压后需手动拷贝头文件与库文件至/usr/local/cuda-11.8/对应目录;不能仅靠 LD_LIBRARY_PATH 临时指定,vLLM 编译阶段会硬检查路径
3Python3.10创建独立 conda 环境verl-envPython 3.11+ 会导致 apex 编译失败,因部分 C++ 扩展未适配新 ABI
4PyTorch2.6.0+cu118使用 PyTorch 官方 cu118 镜像源安装;禁用 pip install torch[rocm],P40 不支持 ROCm
5Apexcommita5e7f3b(2024年中)必须加--config-settings "--build-option=--cpp_ext" --config-settings "--build-option=--cuda_ext"MAX_JOB=32 是为了加速编译,非必需但强烈建议
6verlgit clone 最新版(2025年9月8日)先执行bash scripts/install_vllm_sglang_mcore.sh安装 vLLM;pip install --no-deps -e .--no-deps是关键,避免重装已手动配置好的 torch/apex

重要提醒:所有安装命令均在verl-env环境中执行。每次新开终端后,请先运行conda activate verl-env。不要试图用pip install verl,它会拉取 PyPI 上的旧版(0.1.x),缺少 PPO 训练主入口。

2.2 验证环境是否就绪

进入 Python 交互环境后,逐条执行以下检查:

# 检查 CUDA 可见性与版本 import torch print(torch.__version__) # 应输出 2.6.0+cu118 print(torch.cuda.is_available()) # 必须为 True print(torch.version.cuda) # 应输出 11.8 # 检查 Apex 是否生效 import apex print(apex.__version__) # 应输出类似 '2.6.0' # 检查 verl 导入与版本 import verl print(verl.__version__) # 应输出类似 '0.3.2.dev0'(git commit hash)

若任一检查失败,请立即返回上一步重新安装,不要继续向下走。尤其注意:torch.cuda.is_available()返回 False 通常意味着 CUDA 路径未正确注入,此时需检查~/.bashrc中是否添加了:

export CUDA_HOME=/usr/local/cuda-11.8 export PATH=$CUDA_HOME/bin:$PATH export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

3. 模型与数据准备:轻量化适配是核心

verl 默认配置面向大模型与多卡训练,而我们只有一块 P40。因此必须做两件事:降低计算密度(改数据类型与 attention)、压缩数据体积(选小模型、裁剪数据集)。

3.1 修改 verl 源码以适配 P40 硬件能力

打开 verl 工程根目录,执行全局搜索(注意带双引号):

grep -r '"Bfloat16"' . --include="*.py" grep -r '"flash_attention_2"' . --include="*.py"

将所有匹配结果中的字符串替换为:

  • "Bfloat16""float32"
  • "flash_attention_2""eager"

必须带双引号替换,否则会误改变量名或注释内容。常见需修改的文件包括:

  • verl/trainer/ppo_trainer.py
  • verl/data_provider/dataset.py
  • verl/actor_rollout/vllm_rollout.py
  • verl/utils/config.py

为什么是 float32 而非 float16?
Tesla P40 的 SM 6.1 架构原生不支持 FP16/BF16 计算单元。强行启用会触发 CUDA kernel 编译失败。float32 虽然显存占用翻倍,但它是 P40 唯一稳定支持的浮点格式。别担心速度——P40 的 FP32 算力达 12 TFLOPS,足够支撑 0.5B 模型的单步 PPO 更新。

3.2 数据预处理:GSM8K 到 verl 格式

GSM8K 原始数据是 HuggingFace Dataset 格式(.arrow),verl 要求输入为 Parquet 文件,并且字段需符合 RL 训练结构(prompt,response,reward)。分三步操作:

(1)下载并转换为 Parquet
# 创建数据目录 mkdir -p $HOME/data/gsm8k/raw cd $HOME/data/gsm8k/raw # 使用 hf-mirror 加速下载(国内推荐) hf download openai/gsm8k --repo-type dataset --local-dir . # 转换为 Parquet(保存在同级 fmt_parquet 目录) python -c " from datasets import load_from_disk ds = load_from_disk('.') ds['train'].to_parquet('../fmt_parquet/train.parquet') ds['test'].to_parquet('../fmt_parquet/test.parquet') "
(2)转换为 verl RL 格式

编辑verl/examples/data_preprocess/gsm8k.py,修改以下两处:

# 原始 data_source = "path/to/gsm8k" local_dir = "path/to/save" # 修改为 data_source = "$HOME/data/gsm8k/fmt_parquet" local_dir = "$HOME/data/gsm8k/fmt_rl"

然后运行:

cd verl/examples/data_preprocess python gsm8k.py

生成的train.parquettest.parquet将位于$HOME/data/gsm8k/fmt_rl/,其 schema 包含prompt,chosen,rejected,reward_chosen,reward_rejected字段,符合 verl PPO 输入要求。

3.3 模型下载:Qwen2.5-0.5B-Instruct

该模型权重约 1.1GB,适合 P40 显存。使用huggingface-hub工具下载:

# 确保已安装 pip install huggingface-hub # 下载到本地 hf download Qwen/Qwen2.5-0.5B-Instruct --local-dir $HOME/models/Qwen2.5-0.5B-Instruct

注意路径一致性:后续训练脚本中actor_rollout_ref.model.pathcritic.model.path必须指向此绝对路径,不能用~符号(hydra 配置解析器不展开)。


4. 训练脚本执行:参数即命运

官方 Quick Start 脚本在 P40 上会直接 OOM。以下是经过 7 轮调试后确认可用的最小可行配置(verl-ppo-gsm8k.sh):

#!/bin/bash export HYDRA_FULL_ERROR=1 export VLLM_DTYPE=float32 export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128 PYTHONUNBUFFERED=1 TRITON_MAX_SHARED_MEMORY=49152 python3 -m verl.trainer.main_ppo \ data.train_files=$HOME/data/gsm8k/fmt_rl/train.parquet \ data.val_files=$HOME/data/gsm8k/fmt_rl/test.parquet \ data.train_batch_size=1 \ data.max_prompt_length=256 \ data.max_response_length=256 \ actor_rollout_ref.model.path=$HOME/models/Qwen2.5-0.5B-Instruct \ actor_rollout_ref.actor.optim.lr=1e-6 \ actor_rollout_ref.actor.ppo_mini_batch_size=1 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu=1 \ actor_rollout_ref.rollout.name=vllm \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu=1 \ actor_rollout_ref.rollout.tensor_model_parallel_size=1 \ actor_rollout_ref.rollout.gpu_memory_utilization=0.3 \ actor_rollout_ref.rollout.max_num_batched_tokens=512 \ ++actor_rollout_ref.rollout.enable_chunked_prefill=false \ ++actor_rollout_ref.fsdp_config.cpu_offload=true \ ++actor_rollout_ref.fsdp_config.offload_params=true \ actor_rollout_ref.rollout.max_num_seqs=1 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu=1 \ critic.optim.lr=1e-5 \ critic.model.path=$HOME/models/Qwen2.5-0.5B-Instruct \ critic.ppo_micro_batch_size_per_gpu=1 \ algorithm.kl_ctrl.kl_coef=0.001 \ trainer.logger=console \ trainer.val_before_train=False \ trainer.n_gpus_per_node=1 \ trainer.nnodes=1 \ trainer.save_freq=10 \ trainer.test_freq=10 \ trainer.total_epochs=2 2>&1 | tee $HOME/logs/verl_demo.log

4.1 关键参数解读(为什么这样设)

参数作用不设的后果
data.train_batch_size=11单步训练仅处理 1 条 prompt-response 对设为 2 会触发OutOfResources: shared memory
actor_rollout_ref.rollout.gpu_memory_utilization=0.30.3强制 vLLM 仅使用 30% 显存默认 0.9 会立即 OOM
actor_rollout_ref.rollout.max_num_batched_tokens=512512限制 vLLM 推理时最大 token 总数必须 ≥max_prompt_length + max_response_length,否则启动失败
++actor_rollout_ref.fsdp_config.cpu_offload=truetrue将 FSDP 的 optimizer state 卸载到 CPU不开启则显存峰值超 24GB
TRITON_MAX_SHARED_MEMORY=4915249152显式设置 Triton 共享内存上限为 48MBP40 硬件限制为 48KB,此值单位为 KB

执行前必做

  • 创建日志目录:mkdir -p $HOME/logs
  • 确保train.parquettest.parquet路径可读
  • 运行chmod +x verl-ppo-gsm8k.sh赋予执行权限

5. 常见报错与精准定位方案

所有报错均来自真实运行过程。这里不列错误堆栈,只给现象→根因→动作三段式解法。

5.1 现象:RuntimeError: CUDA error: no kernel image is available for execution on the device

  • 根因:PyTorch 或 CUDA 版本与 P40 架构不匹配(如 CUDA 12.x 编译的 torch 在 P40 上运行)
  • 动作
    1. nvcc --version确认 CUDA 版本为 11.8
    2. python -c "import torch; print(torch.version.cuda)"确认 torch 编译于 CUDA 11.8
    3. 若不符,彻底卸载torchtorchaudio,重装 cu118 版本

5.2 现象:ValueError: Bfloat16 is only supported on GPUs with compute capability of at least 8.0

  • 根因:verl 源码中硬编码了"Bfloat16",未做设备能力检测
  • 动作
    执行全文本替换:sed -i 's/"Bfloat16"/"float32"/g' $(find . -name "*.py")
    注意:必须在 verl 工程根目录执行,且替换后需重新pip install --no-deps -e .

5.3 现象:triton.runtime.errors.OutOfResources: out of resource: shared memory

  • 根因:FlashAttention-2 kernel 需要 ≥80KB 共享内存,P40 仅提供 48KB;或 batch size 过大
  • 动作
    1. 先执行sed -i 's/"flash_attention_2"/"eager"/g' $(find . -name "*.py")
    2. 再检查训练脚本中max_num_batched_tokens是否 ≤512,train_batch_size是否为 1
    3. 若仍报错,追加环境变量export TRITON_CACHE_DIR=/tmp/triton_cache避免缓存污染

5.4 现象:ModuleNotFoundError: No module named 'vllm'

  • 根因scripts/install_vllm_sglang_mcore.sh执行失败,或未激活verl-env
  • 动作
    1. 进入verl/scripts/目录,手动运行bash install_vllm_sglang_mcore.sh
    2. 观察最后是否输出Successfully installed vllm-...
    3. 若失败,检查nvidia-smi是否可见 GPU,gcc --version是否 ≥7.5

6. 总结:这一步,我们到底走通了什么

这不是一篇教你“如何优雅地部署 verl”的文章,而是一份在物理限制下强行打通数据链路的工程日志。我们确认了以下事实:

  • verl 框架本身可在 Tesla P40(CUDA 11.8 + Python 3.10)上完成 import 与基础初始化
  • 通过源码级修改(Bfloat16 → float32,flash_attention_2 → eager),可绕过硬件能力墙
  • Qwen2.5-0.5B-Instruct 模型能在 P40 上完成 PPO 的完整训练循环(至少前 10 步)
  • GSM8K 数据经 verl 标准化后,可被正确加载、分片、构建 RL batch
  • 所有关键参数(batch size、memory utilization、token limit)均有明确阈值边界

当然,它仍有局限:训练速度慢(单步约 7 秒)、无法跑满 epoch(第 9 步后再次 OOM)、不支持多卡扩展。但这些不是 verl 的缺陷,而是 P40 的物理事实。真正的价值在于——你拿到了一把钥匙,能亲手打开 LLM 强化学习的大门,哪怕门后只有一盏微光

下一步,你可以:

  • 尝试更小的模型(如 Phi-3-mini-4k-instruct)进一步压低显存
  • trainer.total_epochs=2改为1,专注验证单轮训练逻辑
  • 查看$HOME/logs/verl_demo.log中的 reward 曲线,确认 KL 散度是否下降

路已经铺到这儿,剩下的,交给你去跑。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 3:33:48

ms-swift模型部署太香了!OpenAI接口秒级响应实测

ms-swift模型部署太香了!OpenAI接口秒级响应实测 1. 这不是“又一个部署工具”,而是开箱即用的推理加速引擎 你有没有遇到过这样的场景:好不容易微调完一个大模型,兴冲冲想部署测试,结果卡在了推理服务搭建环节——v…

作者头像 李华
网站建设 2026/6/15 12:17:06

OFA-SNLI-VE Large效果展示:复杂场景下部分相关(Maybe)判断

OFA-SNLI-VE Large效果展示:复杂场景下部分相关(Maybe)判断 1. 这不是简单的“对错题”,而是理解世界的多维判断 你有没有试过让AI看一张图,再读一段文字,然后问它:“这图和这段话说的是一回事吗?” 大多…

作者头像 李华
网站建设 2026/6/14 21:44:10

万物识别模型推理全过程,附完整操作流程图解

万物识别模型推理全过程,附完整操作流程图解 1. 引言:一张图,到底能“说”出多少中文信息? 你有没有试过把一张随手拍的照片丢给AI,然后它不光认出“这是猫”,还能说出“一只橘猫正趴在米色布艺沙发上打盹…

作者头像 李华
网站建设 2026/6/14 8:43:40

ms-swift MoE模型加速:Megatron并行实测提速10倍

ms-swift MoE模型加速:Megatron并行实测提速10倍 1. 为什么MoE模型训练总卡在显存和速度上? 你有没有遇到过这样的情况:想用Qwen3-MoE或DeepSeek-VL2这类专家混合模型做微调,结果刚跑两步就报“CUDA out of memory”&#xff0c…

作者头像 李华
网站建设 2026/6/14 13:04:16

JFlash烧录STM32程序的系统学习路径

以下是对您提供的博文内容进行 深度润色与结构重构后的专业级技术文章 。我以一位有十年嵌入式系统开发与量产落地经验的工程师视角,彻底摒弃模板化表达、AI腔调和教科书式罗列,转而采用 真实项目语境驱动 工程痛点切入 代码即文档 的写法&#xf…

作者头像 李华
网站建设 2026/6/14 2:27:29

硬件电路中PMU芯片配置的操作指南

以下是对您提供的博文内容进行 深度润色与结构重构后的专业级技术文章 。全文已彻底去除AI生成痕迹,采用真实嵌入式系统工程师口吻撰写,逻辑层层递进、语言精炼有力、案例扎实可信,兼具教学性与工程实战价值。文中所有技术细节均严格依据主…

作者头像 李华