# vLLM **Repository Path**: eulixos/v-llm ## Basic Information - **Project Name**: vLLM - **Description**: No description available - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-06-24 - **Last Updated**: 2026-06-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # openEuler RISC-V vLLM CPU 构建与 Qwen 性能测试脚本使用说明 本文档说明三份脚本的使用顺序、核心命令、RISC-V PyTorch wheel 配置、Qwen 模型自动下载、benchmark 参数含义以及测试结果文件含义。 当前脚本已经在 **RISC-V 服务器** 上测试跑通;ARM 服务器近期暂未重新验证,因此本文命令以 RISC-V 环境为主。ARM 路径仍保留,但在 ARM 服务器重新可用后,需要重新确认 PyTorch wheel、vLLM requirements、NEON/ASIMD 支持以及 torch 安装策略。 本仓库不包含 torch-2.11.0-cp311-cp311-linux_riscv64.whl 文件。在运行 vLLM 构建脚本之前,可先在当前服务器中查找该 wheel: find / -type f \ -name "torch-2.11.0-cp311-cp311-linux_riscv64.whl" \ 2>/dev/null 如果能够找到该 wheel,可以直接使用其现有绝对路径,也可以将其复制或移动到自定义目录。随后在执行构建脚本时,通过 --torch-wheel 参数指定对应路径; 在开始构建之前,建议先确认指定文件确实存在: ls -lh /path/to/torch-2.11.0-cp311-cp311-linux_riscv64.whl 如果在当前服务器中无法找到该 wheel,请联系作者或项目维护者获取所需的 RISC-V PyTorch wheel。 --- ## 一、脚本使用顺序 本文档对应以下三份脚本: 建议按以下顺序执行: 1. `vllm_dep_check_install_openeuler.sh`:用于检测系统基础依赖,并在需要时安装缺失依赖; 2. `vllm_build_install_openeuler.sh`:用于下载 vLLM、创建虚拟环境、安装 Python 依赖并构建 vLLM CPU wheel; 3. `run_qwen_vllm_vlen_steady_perf.sh`:用于自动下载 Qwen 模型,并对 `vlen=0 / 128 / 256` 三组 workspace 执行 steady-state 推理测试和可选 perf 采集。 建议统一设置一个工作根目录: ```bash export WORKSPACE_ROOT=/data/xhn/vllm_auto_test_workspace ``` 在该目录下组织三组 vLLM workspace、模型目录和测试结果目录: ```text $WORKSPACE_ROOT/ ├── vllm_auto_temp_test_workspace_vlen0/ ├── vllm_auto_temp_test_workspace_vlen128/ ├── vllm_auto_temp_test_workspace_vlen256/ ├── models/ │ └── Qwen2.5-0.5B-Instruct/ └── qwen_vllm_vlen_steady_results/ ``` 当前常见 RISC-V 机器硬件 VLEN 为 128 bit 时: ```text vlen=0:作为 scalar/no-RVV 对照组; vlen=128:作为当前硬件匹配的 RVV 测试组; vlen=256:只有硬件实际 VLEN 为 256 bit 时才作为有效测试组。 ``` 如果当前硬件 VLEN=128,构建脚本会阻止不安全的 vlen=256 构建,测试脚本也会自动跳过 vlen256 组。 --- ## 二、步骤 1:系统依赖检测 先执行检测,不安装任何内容: ```bash bash vllm_dep_check_install_openeuler.sh --check ``` 该脚本会检测以下内容: ```text 基础命令:git、gcc、g++、make、cmake、python3、pkg-config 等; Python 功能:python3 -m pip、python3 -m venv; 系统包:python3-devel、python3-pip、numactl-devel、findutils 等; 平台信息:riscv64 / arm64 / x86_64; 系统信息:openEuler 版本、包管理器、发行版类型。 ``` 如果检测到缺失依赖,再执行安装: ```bash bash vllm_dep_check_install_openeuler.sh --install -y ``` 注意事项: ```text 1. 该脚本不会执行系统升级; 2. 该脚本不会全局安装 vLLM、PyTorch、numpy 等 Python 包; 3. dnf/yum 安装前会进行 dry-run 事务预检查; 4. 如果 dry-run 显示会触发升级、删除、替换或降级已有包,应停止并人工确认。 ``` --- ## 三、步骤 2:构建 vLLM workspace 构建前需要将脚本压缩包中的 RISC-V PyTorch wheel 复制到服务器,并在构建命令中通过 `--torch-wheel` 指定路径。 当前使用的 RISC-V torch wheel 为: ```text torch-2.11.0-cp311-cp311-linux_riscv64.whl ``` 示例路径: ```bash export TORCH_WHEEL=/data/xhn/vllm_auto_test/wheels/torch-2.11.0-cp311-cp311-linux_riscv64.whl ls -lh "$TORCH_WHEEL" ``` RISC-V 构建时必须使用 `linux_riscv64` 对应的 wheel;ARM 服务器不能使用该 wheel。 ### 1. 构建 vlen=0 scalar 对照组 ```bash bash vllm_build_install_openeuler.sh \ --workspace "$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen0" \ --vllm-ref main \ --torch-wheel "$TORCH_WHEEL" \ --riscv-rvv-vlen 0 \ --force-clean ``` 说明: ```text --riscv-rvv-vlen 0:表示 scalar/no-RVV 对照路径; --torch-wheel:必须指向 RISC-V 可用 PyTorch wheel; --force-clean:删除该 workspace 下旧源码和旧 venv 后重新构建。 ``` ### 2. 构建 vlen=128 RVV 测试组 ```bash bash vllm_build_install_openeuler.sh \ --workspace "$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen128" \ --vllm-ref main \ --torch-wheel "$TORCH_WHEEL" \ --riscv-rvv-vlen 128 \ --force-clean ``` 说明: ```text 当前硬件 VLEN=128 bit 时,vlen=128 是有效 RVV 测试组; 构建脚本会读取硬件 vlenb,并对请求的 VLEN 做安全校验。 ``` ### 3. 构建 vlen=256 RVV 测试组 只有在硬件实际 VLEN 支持 256 bit 时再构建: ```bash bash vllm_build_install_openeuler.sh \ --workspace "$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen256" \ --vllm-ref main \ --torch-wheel "$TORCH_WHEEL" \ --riscv-rvv-vlen 256 \ --force-clean ``` 如果当前机器硬件 VLEN=128,不应强行构建 vlen=256,否则可能出现“编译通过但运行模型时在 `_C.abi3.so` 崩溃”的问题。 ### 4. 构建日志位置 每个 workspace 的构建结果一般保存在: ```text $WORKSPACE/results/_main/ ``` 重点查看: ```text logs/main.log logs/python_deps.log logs/build.log logs/vllm_runtime_extra_deps.log logs/import_test.log env_info.txt pip_freeze.txt summary.txt vllm_commit.txt ``` --- ## 四、步骤 3:运行 Qwen steady-state benchmark ### 1. 使用默认 benchmark 参数 如果构建时采用的是: ```text --workspace $WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen0 --workspace $WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen128 --workspace $WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen256 ``` 则测试时只需要传入 `WORKSPACE_ROOT` 和 `MODEL_ID`: ```bash WORKSPACE_ROOT=/data/xhn/vllm_auto_test_workspace \ MODEL_ID=Qwen/Qwen2.5-0.5B-Instruct \ bash run_qwen_vllm_vlen_steady_perf.sh ``` 测试脚本会自动推导: ```text WORKSPACE_VLEN0=$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen0 WORKSPACE_VLEN128=$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen128 WORKSPACE_VLEN256=$WORKSPACE_ROOT/vllm_auto_temp_test_workspace_vlen256 MODEL_DIR=$WORKSPACE_ROOT/models/Qwen2.5-0.5B-Instruct OUT_ROOT=$WORKSPACE_ROOT/qwen_vllm_vlen_steady_results/<时间戳> ``` ### 2. 显式设置 benchmark 负载参数 ```bash WORKSPACE_ROOT=/data/xhn/vllm_auto_test_workspace \ MODEL_ID=Qwen/Qwen2.5-0.5B-Instruct \ TEXT_NUM_PROMPTS=4 \ TEXT_OUTPUT_LEN=16 \ TEXT_REPEAT=3 \ LATENCY_NUM_ITERS=3 \ LATENCY_OUTPUT_LEN=16 \ LONG_NUM_DOCUMENTS=2 \ LONG_DOCUMENT_LENGTH=256 \ LONG_OUTPUT_LEN=16 \ bash run_qwen_vllm_vlen_steady_perf.sh ``` 注意:每一行环境变量后面都需要保留反斜杠 `\`,否则后续变量不会传给脚本。 ### 3. benchmark 参数含义 以下参数属于 **benchmark 负载规模参数**,用于控制测试任务本身,不属于 perf 参数。 | 参数 | 含义 | 主要影响 | |---|---|---| | `TEXT_NUM_PROMPTS` | `01_Text_Throughput` 阶段每轮提交的 prompt 数量 | 值越大,批量吞吐测试负载越大 | | `TEXT_OUTPUT_LEN` | `01_Text_Throughput` 阶段每条请求最多生成的 token 数 | 值越大,decode 阶段越长 | | `TEXT_REPEAT` | `01_Text_Throughput` 阶段重复执行 batch generate 的次数 | 值越大,吞吐统计越稳定,但耗时越长 | | `LATENCY_NUM_ITERS` | `02_Latency` 阶段单请求 generate 的重复次数 | 值为 1 时延迟统计只有一个样本 | | `LATENCY_OUTPUT_LEN` | `02_Latency` 阶段每次单请求最多生成的 token 数 | 值越大,单次延迟越长 | | `LONG_NUM_DOCUMENTS` | `03_Long_Document_QA` 阶段构造的长文档请求数量 | 值越大,长输入场景负载越大 | | `LONG_DOCUMENT_LENGTH` | `03_Long_Document_QA` 阶段构造长文档输入的长度规模 | 主要影响 prefill 阶段和 KV cache 压力 | | `LONG_OUTPUT_LEN` | `03_Long_Document_QA` 阶段每条长文档请求最多生成的 token 数 | 值越大,长文档场景的 decode 时间越长 | 如果 `LATENCY_NUM_ITERS=1`,则同一 benchmark 下: ```text latency_mean_s = latency_min_s = latency_max_s = latency_p50_s = latency_p90_s ``` 这是正常现象,因为只有一个延迟样本。 ### 4. perf 参数含义 真正控制 perf 的参数是: | 参数 | 含义 | |---|---| | `RUN_PERF=0` | 只运行 benchmark,不采集 perf 硬件计数 | | `RUN_PERF=1` | 在正式测试阶段 attach perf,并生成 `perf_summary.csv` | | `PERF_EVENTS` | 指定 perf 采集事件,例如 cycles、instructions、cache-misses、L1/LLC miss 等 | --- ## 五、模型自动下载说明 测试脚本默认: ```bash MODEL_ID=Qwen/Qwen2.5-0.5B-Instruct MODEL_DIR=$WORKSPACE_ROOT/models/Qwen2.5-0.5B-Instruct HF_ENDPOINT=https://hf-mirror.com AUTO_DOWNLOAD_MODEL=1 ``` 默认下载必需文件: ```text config.json tokenizer_config.json tokenizer.json model.safetensors ``` 默认尝试下载可选文件: ```text generation_config.json vocab.json merges.txt ``` 如果模型目录已经包含 `config.json` 和权重文件,脚本会跳过下载。 强制重新下载: ```bash FORCE_MODEL_DOWNLOAD=1 bash run_qwen_vllm_vlen_steady_perf.sh ``` 如果使用分片模型,需要手动指定文件列表,例如: ```bash MODEL_DOWNLOAD_REQUIRED_FILES="config.json tokenizer_config.json tokenizer.json model.safetensors.index.json model-00001-of-00002.safetensors model-00002-of-00002.safetensors" \ bash run_qwen_vllm_vlen_steady_perf.sh ``` --- ## 六、输出结果查看 测试完成后,结果目录为: ```bash echo "$OUT_ROOT" ``` 如果没有手动设置 `OUT_ROOT`,结果目录默认位于: ```text $WORKSPACE_ROOT/qwen_vllm_vlen_steady_results/<时间戳> ``` 重点查看: ```bash cat "$OUT_ROOT/status.csv" cat "$OUT_ROOT/metrics_summary.csv" cat "$OUT_ROOT/perf_summary.csv" cat "$OUT_ROOT/build_inspection.csv" cat "$OUT_ROOT/skipped.csv" cat "$OUT_ROOT/result_field_description.md" ``` ### 1. `status.csv` 用于查看每个 workspace、每个 benchmark 是否成功完成。 | 字段 | 含义 | |---|---| | `label` | 测试组标签,例如 `vlen0_scalar`、`vlen128_rvv` | | `requested_vlen` | 该组请求的 VLEN 值 | | `benchmark` | benchmark 阶段名称 | | `exit_code` | 该阶段执行返回码,`0` 通常表示成功 | | `workspace` | 本阶段使用的 vLLM workspace | | `output_log` | Python/vLLM 运行日志 | | `perf_file` | 该阶段 perf 原始解析结果 | | `metrics_json` | 该阶段推理侧指标 JSON 文件 | ### 2. `metrics_summary.csv` 用于查看推理侧 benchmark 指标。 | 字段 | 含义 | |---|---| | `engine_init_time_s` | vLLM engine 初始化耗时,包括模型加载、profile、KV cache 创建和内部 warmup | | `script_warmup_time_s` | 脚本级 warmup generate 耗时,不计入正式 benchmark | | `elapsed_s` | 当前 benchmark 正式阶段总耗时 | | `prompt_tokens` | 当前阶段输入 token 总数 | | `output_tokens` | 当前阶段输出 token 总数 | | `total_tokens` | 输入 token 与输出 token 之和 | | `output_tok_s` | 输出 token 吞吐,计算方式为 `output_tokens / elapsed_s` | | `total_tok_s` | 总 token 吞吐,计算方式为 `total_tokens / elapsed_s` | | `latency_mean_s` | 请求延迟平均值 | | `latency_min_s` | 请求延迟最小值 | | `latency_max_s` | 请求延迟最大值 | | `latency_p50_s` | 请求延迟 p50 | | `latency_p90_s` | 请求延迟 p90 | ### 3. `perf_summary.csv` 用于查看 perf 硬件计数指标,仅在 `RUN_PERF=1` 时有有效数据。 | 字段 | 含义 | |---|---| | `Duration` | perf 观测到的阶段持续时间 | | `Task_Clock` | 任务实际占用 CPU 的时间 | | `Cycles` | CPU cycle 数 | | `Instructions` | 执行指令数 | | `Cache_Ref` | cache 引用次数 | | `Cache_Misses` | cache miss 次数 | | `Branches` | 分支指令次数 | | `Branch_Misses` | 分支预测失败次数 | | `L1_Load` | L1 data cache load 次数 | | `L1_Miss` | L1 data cache load miss 次数 | | `LLC_Load` | Last Level Cache load 次数 | | `LLC_Miss` | Last Level Cache load miss 次数 | | `IPC` | 每 cycle 执行指令数,计算方式为 `Instructions / Cycles` | ### 4. `build_inspection.csv` 用于记录构建产物和 RVV 指令粗略统计。 | 字段 | 含义 | |---|---| | `cmake_vlen` | 从构建日志中提取的 `VLLM_RVV_VLEN` | | `so_file` | vLLM 原生扩展 `_C*.so` 路径 | | `so_size_bytes` | `.so` 文件大小 | | `so_sha256` | `.so` 文件 sha256 | | `rvv_instruction_count` | 对 `.so` 反汇编后粗略统计到的 RVV 指令数量 | ### 5. `skipped.csv` 用于记录被跳过的测试组。 常见情况: ```text vlen256 在硬件 VLEN=128 时自动跳过。 ``` 每个 workspace 的详细运行日志位于: ```text $OUT_ROOT/vlen0_scalar/output.log $OUT_ROOT/vlen128_rvv/output.log $OUT_ROOT/vlen256_rvv/output.log ``` --- ## 七、重要注意事项 ### 1. 不要随意升级系统依赖 当前脚本设计目标是不破坏系统环境。依赖检测脚本不会主动系统升级。看到 pip 提示: ```text A new release of pip is available ``` 一般可以忽略,不建议因为该提示手动执行全局升级。 ### 2. RISC-V 必须使用 RISC-V torch wheel 重点文件: ```text torch-2.11.0-cp311-cp311-linux_riscv64.whl ``` 如果该 wheel 不存在,应先准备该文件,再执行 vLLM 构建。不要在 RISC-V 上依赖普通 PyTorch CPU index 直接安装官方 wheel。 ### 3. vlen=256 不适合在 VLEN=128 硬件上运行 如果当前硬件检测结果为: ```text Detected hardware VLEN bits: 128 ``` 则有效测试组为: ```text vlen0_scalar vlen128_rvv ``` `vlen256_rvv` 应跳过。不要把 vlen=256 的结果当作当前机器上的有效对比结果。 ### 4. warmup 很慢是当前 RISC-V vLLM CPU 路径的正常现象 在 RISC-V CPU 上,vLLM engine 初始化可能输出: ```text starting vLLM engine init... Warming up model for the compilation... ``` 该阶段可能持续 10 到 20 分钟。只要 CPU 仍在工作,且没有报错,不一定是卡死。 ### 5. 代理与网络 测试脚本默认: ```bash HF_ENDPOINT=https://hf-mirror.com CLEAR_PROXY=0 ``` 含义: ```text CLEAR_PROXY=0:保留当前 shell 中已有代理; CLEAR_PROXY=1:清理 http_proxy、https_proxy 等代理变量。 ``` 如果服务器必须走代理,则不要设置 `CLEAR_PROXY=1`,并提前确认: ```bash env | grep -i proxy curl -I https://hf-mirror.com ``` ### 6. GVM / shell 环境污染 部分 RISC-V 开发板 root 环境可能安装了 GVM,导致 `cd` 被 hook,出现: ```text /root/.gvm/scripts/env/cd: line 63: GVM_DEBUG: unbound variable ``` 当前构建脚本的 `run_bash_logged()` 已尽量使用 `bash --noprofile --norc` 规避。如果仍遇到该问题,可先执行: ```bash export GVM_DEBUG=0 unset -f cd 2>/dev/null || true ``` 再运行脚本。 ### 7. ARM 服务器当前未重新验证 脚本保留 ARM 路径,但本文命令重点面向 RISC-V。ARM 服务器近期不可用,因此 ARM 运行前需要重新验证: ```text PyTorch wheel 来源; vLLM requirements 是否能直接安装; NEON/ASIMD 支持; 是否需要额外调整 torch 安装策略。 ```