ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UCM Toolkit precheck 部署环境预检:从驱动、内核到存储带宽的一站式主机体检

UCM Toolkit precheck 部署环境预检:从驱动、内核到存储带宽的一站式主机体检
  • 大模型
  • 人工智能
  • 缓存

【免费下载链接】unified-cache-management

Unified Cache Manager(推理记忆数据管理器),是一款以KV Cache为中心的推理加速套件,其融合了多类型缓存加速算法工具,分级管理并持久化推理过程中产生的KV Cache记忆数据,扩大推理上下文窗口,以实现高吞吐、低时延的推理体验,降低每Token推理成本。

项目地址:https://gitcode.com/ModelEngine/unified-cache-management
点击查看免费下载

部署 Unified Cache Manager(UCM,推理记忆数据管理器)前,主机环境是否满足要求,往往决定了引擎能否顺利启动、KV Cache 的落盘与回读能否跑出预期带宽。UCM Toolkit 内置的precheck工具就是为这一场景设计的环境预检入口:它一次扫描服务栈版本、uc-manager版本、加速器驱动、内核、共享内存、内核 AIO 资源池与存储带宽七类指标,逐项给出PASS/WARN/FAIL结论和修复建议,并支持 JSON 输出与阈值配置。读完本文,你将掌握precheck的全部检查项与默认判定标准、命令行与配置文件的使用方式、带宽基准的扫描与解读逻辑,以及如何结合 外部缓存验证 完成一次完整的部署前体检。

为什么需要部署前预检

UCM 以 KV Cache 为中心,运行期高度依赖主机上的加速器驱动、大容量共享内存与高速缓存介质:KV 数据要写入/读取本地存储(例如 Posix Store),块交换依赖/dev/shm这样的共享内存,传输路径则受制于内核 AIO 资源与存储吞吐。这些环节任何一个不达标,都可能表现为引擎启动失败、缓存加载超时或 I/O 吞吐远低于预期。

precheck的价值在于把这类问题前置到服务启动之前。官方文档(源码)明确给出了三个典型使用时机:

  • 首次部署或更换机器:将新主机对照预检标准逐项核对,确认驱动、内核、共享内存等满足要求;
  • 排查启动失败或缓存加载问题:当怀疑问题与驱动、共享内存或内核资源有关时,用预检快速定位环境因素;
  • 评估缓存目录:在选定挂载点(--mount-path)上做一次初始读写带宽摸底,判断该路径是否值得用作 KV 缓存介质。

工具本身由 adapter.py 以ToolAdapter形式注册为ucm-toolkit run precheck子命令(别名pre_check,注册测试见 test_precheck_toolkit.py)。CLI 的准备方式见 toolkit 安装指南,其入口实现位于 cli.py。

检查项全景:七类检查与默认判定标准

precheck共包含七类检查,其中"廉价"的环境检查(版本、驱动、内核、内存、AIO)只依赖 Python 标准库,任何主机上都能运行;存储带宽基准额外依赖 Linux、NumPy 与可加载的原生 UCM Posix Store(见 checks.py 的模块说明)。执行顺序固定为 cli.py 中定义的DEFAULT_ORDER:先跑廉价的版本信息检查,再做硬性检查,最后才跑耗时的带宽基准。

下表来自原文档并补充了源码确认的默认值:

检查项默认判定标准含义
服务栈与uc-manager版本INFO,仅展示记录已安装的 vllm / vllm-ascend / sglang 与 UCM 包版本
加速器驱动缺少驱动直接 FAIL;CUDA 计算能力要求 ≥ 8.0;Ascend HDK 要求严格高于 25.2.0,否则 WARN通过设备查询命令读取
内核版本至少 5.10 系列按主/次版本号比较
/dev/shm低于 512 GiB 时 WARN预检阈值;UCM 实际容量取决于配置与模型
AIO 资源INFO,仅展示读取内核限制与当前用量
存储带宽最佳聚合配置低于 8 GB/s 时 WARN阈值可调,受缓存与负载影响

1. 服务栈版本(INFO)

check_serving_stack通过importlib.metadata或模块导入方式探测vllm、vllm-ascend、sglang的安装版本并原样展示(checks.py)。该检查永不失败:即使三者都未安装,也只是以INFO状态记录no vllm / vllm-ascend / sglang detected。注意 vllm-ascend 版本会做一次归一化(去掉.postN与rcN后缀,见 parseutil.py 的normalize_vllm_ascend_version),便于与补丁版本规范对齐。

2.uc-manager版本(INFO)

check_uc_manager_version扫描当前环境中所有以uc-manager命名的发行版(含 Fork 与变体),只报告包名与版本、不导入 UCM 代码(checks.py)。这对于确认"装的是哪套 UCM"很有用,尤其在多版本共存的环境中。

3. 加速器驱动(WARN)

check_accelerator_driver自动识别平台:优先使用nvidia-smi,否则回退到npu-smi info。两个命令都不存在时,直接判定 FAIL——UCM 必须有 GPU/NPU,纯 CPU 主机不能算通过(checks.py)。

  • NVIDIA 平台:通过nvidia-smi --query-gpu=name,driver_version,compute_cap --format=csv,noheader,nounits获取每张卡的型号、驱动与计算能力,逐卡扫描后取所有卡中最低的计算能力与阈值(默认 8.0)比较。低于 8.0 会 WARN,并提示"使用 Ampere 或更新的 GPU"(checks.py)。
  • Ascend 平台:从npu-smi info输出中启发式提取 HDK 版本。解析优先级是:显式HDK Version标签 →Driver Version标签 → banner 上的Version: X.Y.Z字段(部分固件只在 banner 上暴露版本,见 parseutil.py)。HDK 要求严格大于25.2.0,相等也判 WARN(checks.py)。测试用例用真实 openEuler 25.5.2 banner 验证了该回退逻辑(test_precheck.py)。

4. 内核版本(FAIL,硬性)

check_kernel_version通过uname -r(失败时回退platform.release())读取内核版本,按major.minor与阈值(默认5.10)比较(checks.py)。"至少 5.10 系列"意味着:

  • 5.10.0-216.0.0.115.oe2203sp4.aarch64(openEuler 22.03 的 5.10 LTS 回移构建)→ 通过;
  • 5.11、6.8.0-25-generic→ 通过;
  • 5.9→ FAIL。

源码注释明确指出该标准与真实 UCM 部署环境(openEuler 22.03 自带 5.10.0- 系列内核)一致。边界用例在 test_precheck.py 的TestKernelBoundary中逐一验证。低于阈值时,修复建议会直接给出"升级到 5.10 或更新内核(例如 openEuler 22.03 LTS-SP4)"。

5./dev/shm共享内存(WARN)

check_memory_shm通过os.statvfs("/dev/shm")读取总量与可用量(checks.py)。总量低于 512 GiB 时 WARN,提示"扩大/dev/shm至 ≥ 512 GiB(UCM KV-cache 页缓存需要它)"。这一阈值的定位是"预检下限",文档特意强调:UCM 实际容量取决于配置与模型。注意/dev/shm无法读取时会 WARN 而不是 FAIL,因为statvfs是 POSIX 专属接口,非 Linux 平台或未挂载时返回不可用。

6. 内核 AIO 资源池(INFO)

check_aio_resources读取/proc/sys/fs/aio-max-nr与/proc/sys/fs/aio-nr,并据此估算可并发的 AIO worker 数(checks.py):

max_aio_workers = (aio_max_nr - aio_nr) // aio_queue_depth

其中aio_queue_depth默认 4096(对应每个 aio store 上下文调用io_setup(queueDepth)时从内核 AIO 池预留的事件数)。该检查只做信息展示、从不判失败,但其输出直接关系到带宽基准中 aio 引擎的可用性(见下文"带宽基准"一节)。测试用aio-max-nr=65536、aio-nr=4096验证了max_aio_workers=15的推导(test_precheck.py)。

7. 存储带宽(WARN)

见后文专门的"带宽基准深度解读"小节。

运行预检:从环境检查到带宽基准

最基本的一条命令即可完成全部检查(无挂载路径时带宽检查自动跳过):

ucm-toolkit run precheck

原文档给出的四种典型用法:

# 只做环境检查,跳过耗时的带宽基准 ucm-toolkit run precheck --skip-bandwidth # 在指定缓存目录上做读写带宽摸底 ucm-toolkit run precheck --mount-path /mnt/ucm-cache-test # 只跑内核与加速器驱动两项 ucm-toolkit run precheck --only kernel --only accelerator_driver # 环境检查 + 机器可读 JSON 输出 ucm-toolkit run precheck --skip-bandwidth --json

几个关键行为(均可在 cli.py 中印证):

  • --only/--skip可重复:--only将执行集合缩减到指定检查项;--skip从默认集合中排除指定项。两者都支持小写名称,遇到未知检查名会报错并以退出码 2 结束(cli.py)。
  • 带宽检查的先决条件:不提供--mount-path(或配置中的mount_path)时带宽检查以SKIP状态跳过并提示"set --mount-path to the UCM cache mount point";非 Linux(os.name != "posix")平台同样跳过;挂载路径不存在或不是目录时 WARN(bandwidth.py)。
  • 原生依赖缺失:无法导入ucm(含 C++ Posix Store)或缺少 NumPy 时,带宽检查以"跳过 + 警告"收场。源码还处理了一个隐蔽场景:当仓库根目录在sys.path上、且源码树ucm/不完整时,会先把仓库根路径从sys.path剔除并清掉已缓存的ucm.*子模块,强制从 site-packages 重新导入,避免源码树遮蔽已安装包(bandwidth.py)。
  • --json:输出机器可读的 JSON,包含每个检查项的severity/status/value/threshold/detail/remediation/raw以及顶层failed/warned布尔值(reporter.py),便于保存和跨环境比对。
  • --verbose:打印额外细节,例如每个 worker 每个 epoch 的 dump/load/mixed 耗时与带宽。

解读结果:状态、退出码与--strict

状态体系

每个检查项包含两个维度:severity(INFO/WARN/FAIL,声明检查类别)与status(PASS/WARN/FAIL/SKIP/OK/INFO,本次的具体结论),定义见 reporter.py。文本输出以带颜色的状态行呈现,每项下方缩进打印threshold:与fix:修复建议——fix行只在 WARN / FAIL / SKIP 且携带建议时出现(reporter.py)。结尾会汇总Result: PASSED / PASSED (with warnings) / FAILED与各状态计数。

退出码

退出码逻辑在 reporter.py 的overall_failed与 cli.py:

退出码含义
0全部通过(无 FAIL,且未启用 strict 时允许 WARN)
1存在 FAIL,或--strict下存在 WARN
2CLI 用法错误(未知检查名、非法引擎/模式、配置解析失败等)

要点:INFO 从不影响退出码;WARN 默认放行,只有显式加--strict才会把 WARN 视为失败(测试覆盖见 test_precheck.py)。另外,任何单个检查抛出的异常都不会中断整轮预检——该检查会被记录为FAIL(detail 注明异常类型与消息)后继续执行后续项(cli.py)。

与验证环节的衔接

预检通过只代表主机环境达标,不等于缓存链路已打通。文档明确要求:通过 precheck 后,仍需要引擎启动 + 外部缓存验证,通过"首个请求落盘、重启后回放命中"来确认外部缓存复用正确。

配置阈值与加载优先级

配置来源与优先级

阈值与带宽矩阵的加载优先级为(config.py):

代码内置常量(兜底) → precheck.defaults.json(随包发布) → --config FILE → CLI 标志
  • 代码常量是 JSON 缺失时的兜底,定义在 config.py;
  • 随包发布的 precheck.defaults.json 是运行时默认值,改阈值只改数据、不动代码;
  • --config FILE在默认值之上做增量覆盖(分层逻辑见 config.py:先加载默认 JSON,再叠加用户文件);
  • CLI 标志优先级最高,覆盖一切。

JSON 不需要额外解析器;YAML 则要求安装 PyYAML,否则报错YAML config requires PyYAML; install it or use a .json config file。

默认值一览

precheck.defaults.json 的完整内容即当前版本的默认阈值:

{ "mount_path": null, "kernel_min": "5.10", "cuda_min_compute_cap": 8.0, "ascend_min_hdk": "25.2.0", "shm_min_gib": 512.0, "bandwidth": { "shard_sizes": ["180k", "8m"], "worker_counts": [1, 8, 16], "engines": ["psync", "aio"], "modes": ["dump", "read", "mix"], "block_number": 32, "shard_number": 1, "dump_epochs": 8, "load_epochs": 8, "mixed_epochs": 8, "rw_ratio": 4, "barrier_timeout": 60, "combo_timeout": 120, "aio_queue_depth": 4096, "threshold_gb": 8.0 } }

覆盖文件示例

原文档给出的覆盖文件展示了如何在不改动默认带宽矩阵的前提下调整个别项。注意该示例把shard_sizes换成了["180k", "1m"]、block_number提到 64,并保留了shm_min_gib的默认值:

{ "mount_path": "/mnt/ucm-cache-test", "kernel_min": "5.10", "cuda_min_compute_cap": 8.0, "ascend_min_hdk": "25.2.0", "bandwidth": { "shard_sizes": ["180k", "1m"], "worker_counts": [1, 16], "engines": ["psync", "aio"], "block_number": 64, "shard_number": 1, "dump_epochs": 32, "load_epochs": 32, "threshold_gb": 8.0 } }

用配置文件运行时,务必不要加--quick,否则指定 epoch 数会被减半(--quick的实现就是把 dump/load/mixed epochs 各自max(1, n // 2),见 config.py):

ucm-toolkit run precheck --config /path/to/precheck.json

注意:配置文件中的大小字符串统一按 1024 进制解析(180k→ 184320 字节、1m→ 1048576 字节,见 parseutil.py 的parse_size),并支持k/K/m/M/g、Ki、MiB等多种后缀写法。

CLI 标志速查

以下标志表来自 cli.py 的参数定义,与文档保持一致并补充了默认值:

标志用途
--mount-path PATH带宽测试目录(必填才跑带宽基准)
--only CHECK/--skip CHECK只跑 / 跳过指定检查,可重复
--skip-bandwidth只做环境检查,跳过带宽基准
--shard-sizes LIST分片大小列表,如180k,1m
--workers LISTworker 数列表,如1,16
--engines LISTI/O 引擎,psync/aio的子集(默认 psync 和 aio)
--modes LIST每个组合执行的阶段,dump,read,mix的子集
--threshold GB带宽告警阈值(GB/s),默认 8.0
--block-number N每次 dump/load 扫描的块数,默认 32
--dump-epochs N每组合 dump 扫描轮数,默认 8
--load-epochs N每组合 load 扫描轮数,默认 8
--mixed-epochs N读重混合扫描轮数(每轮 1 次 dump + rw_ratio 次 load),默认 8
--rw-ratio N混合阶段读写比(读重),默认 4;0 禁用混合
--quick减半各阶段 epoch 数,加速运行
--kernel-min VER内核阈值,默认5.10(要求严格大于等于)
--cuda-min-compute-cap NCUDA 计算能力阈值,默认 8.0
--ascend-min-hdk VERAscend HDK 阈值,默认25.2.0(要求严格大于)
--strict将 WARN 视为失败(影响退出码)
--json输出机器可读 JSON
--no-color禁用 ANSI 颜色(非 TTY 时自动禁用)
--verbose显示额外细节

非法值处理:--engines/--modes传入不在允许集合内的值会直接以退出码 2 终止(cli.py)。

带宽基准深度解读

带宽基准是 precheck 中最复杂、也最贴近 UCM 实际 I/O 特征的部分,实现在 bandwidth.py。

扫描矩阵与阶段语义

默认矩阵扫描2 个分片大小(180 KiB、8 MiB)× 3 档 worker 数(1 / 8 / 16)× 2 种引擎(psync / aio),共 12 个组合(combo)。每个组合按--modes(默认dump,read,mix)运行三个阶段:

  • dump(写):worker 通过UcmPipelineStore(store_pipeline="Posix")调用dump_data并wait,统计写带宽;
  • read(读):对应load_data,统计读带宽;
  • mix(读重混合):每轮先 1 次 dump 扫掠、再rw_ratio次 load 扫掠,整体计时。rw_ratio默认 4,即1 写 4 读。混合吞吐按(1 + rw_ratio) × sweep_bytes / elapsed计算(bandwidth.py)。注释点明其模拟的是真实 KV 缓存访问模式——"写一次、读多次"。

每个阶段默认跑 8 个 epoch,输出每 worker 的均值、标准差、min/max,以及worker 数 × 每 worker 带宽的聚合值。worker 之间通过multiprocessing.Barrier在启动时和每个 epoch 后同步,确保所有 worker 同时开始 I/O、且内核 aio 队列在下一轮突发提交前排空(bandwidth.py)。

聚合与"最佳"选择逻辑

工具的判据逻辑值得细读(bandwidth.py):

  • 每个 combo 产出最多四个指标:dump、load、comprehensive(dump 与 load 均运行时取两者均值)、mixed;
  • headline_bw的取值偏好为:mixed > comprehensive > dump > load,再乘以 worker 数得到聚合吞吐;
  • pick_best取聚合吞吐最高的成功 combo 作为整体代表;
  • best_per_metric则对每个跑过的指标分别取"该指标聚合最高"的 combo——不同指标的最佳 combo 可能不同(测试test_best_per_metric_different_combos专门验证了这一点,test_precheck.py);
  • 最终状态判定bandwidth_status:只有每个指标的"最佳聚合"都达到阈值(默认 8 GB/s)才 PASS,否则 WARN(test_precheck.py 覆盖了 dump 低于阈值、load 达标的 WARN 场景)。

报告中会列出每个指标的最佳组合(如dump best=... GB/s (shard=...B workers=... engine=...) [PASS/WARN]),以及完整矩阵中每个 combo 的逐项统计。

aio 引擎探测与内核资源上限

aio 引擎在部分磁盘上会阻塞甚至死锁(worker.wait(task)可能阻塞在不可中断的内核 aio 系统调用上,连 SIGKILL 都无法打断)。因此工具在跑矩阵前先对每个非 psync 引擎做一次"快速探测"(单 worker、单块 dump,15 秒超时),失败或超时则跳过该引擎的组合并提示改用 psync(bandwidth.py)。

同时,工具会读取/proc/sys/fs/aio-max-nr与aio-nr:每个 aio store 上下文调用io_setup(queue_depth)会从内核 AIO 池预留queue_depth(默认 4096)个事件,如果N workers × queue_depth超过可用池(aio-max-nr - aio-nr),后面的io_setup会以EAGAIN失败并导致组合死锁。因此工具会:

  • 将 aio worker 数上限封顶到内核实际可支持的数量(max_aio_workers = 可用事件数 // queue_depth);
  • 超出上限的 aio 组合直接标记为失败(skipped: only N aio workers available);
  • 提示echo 1048576 > /proc/sys/fs/aio-max-nr来调高内核上限(bandwidth.py)。

超时与同步保障

每个 combo 有combo_timeout(默认120 秒)的硬性截止;超时后先 SIGTERM、再 SIGKILL 兜底清理挂起的 worker(bandwidth.py)。启动屏障有barrier_timeout(默认 60 秒)作为兜底——正常情况下某个 worker 创建 store 失败会调用barrier.abort()立即唤醒幸存者,超时只在 abort 未送达时生效。另外,工具会把TORCH_DEVICE_BACKEND_AUTOLOAD=0、GLOG_minloglevel=2、GLOG_stderrthreshold=2设入环境,并默认把 worker 的 stderr 重定向到/dev/null,屏蔽 torch_npu 自动加载与 glog 的噪音输出(bandwidth.py)。

结果解读注意事项

  • 非 Direct I/O 的读取可能被 OS 页缓存服务:文档提醒,read阶段的吞吐应理解为"被测路径在该缓存状态下能达到的吞吐",测量存储介质时应说明 I/O 模式(是否io_direct/O_DIRECT)与缓存状态。修复建议中也会出现"confirm io_direct/O_DIRECT settings"。
  • 带宽数字是路径吞吐而非磁盘标称值:聚合带宽受缓存、负载、worker 数共同影响,阈值(默认 8 GB/s)只是预检下限。
  • 每个 combo 输出的是n个 epoch 样本的均值与波动(std/min/max),n即该方向收集到的样本数,可在报告中核对。

开发与测试

源码结构

precheck 的实现全部位于 toolkit/ucm_toolkit/tools/precheck/,模块职责清晰:

模块职责
cli.py参数解析、检查调度、退出码
checks.py六类环境检查的具体实现
bandwidth.py带宽矩阵基准、引擎探测、聚合判据
config.py阈值与带宽矩阵的默认值、分层加载、CLI 覆盖
precheck.defaults.json随包发布的默认配置(纯数据)
reporter.py结果模型、文本/JSON 渲染、退出码判定
parseutil.py版本、字节大小、nvidia-smi / npu-smi 输出解析
adapter.pyToolkit 工具注册与run/doctor适配

现有测试与运行方式

现有测试覆盖阈值/配置处理与 Toolkit 分发两层,但不跑硬件带宽验收测试(那是真机上的事,见文档说明):

  • test_precheck.py:纯标准库单测,覆盖版本/大小解析、内核边界(5.10 系列判定)、npu-smi 解析、配置分层、带宽选择与状态判定、reporter 退出码、AIO 资源推导、加速器驱动判定(用 mock 的subprocess/os/import,跨主机可复现);
  • test_precheck_toolkit.py:覆盖 Toolkit 集成——precheck注册为顶层工具(别名pre_check)、ucm-toolkit list可见、run precheck --help可分发、doctor precheck正常输出。

在仓库根目录运行:

cd toolkit python -m unittest tests.test_precheck tests.test_precheck_toolkit -v

需要精确查看当前版本的可用标志时,直接执行:

ucm-toolkit run precheck --help

部署前使用建议

将precheck纳入部署流程时,建议按如下顺序使用:

  1. 先环境后带宽:首次部署先用--skip-bandwidth快速核对驱动、内核、/dev/shm与 AIO 资源,任何 FAIL 项按fix:建议处理后再进入下一步;
  2. 再摸底缓存目录:对候选缓存挂载点执行--mount-path <目录> --config <覆盖文件>,观察各指标(尤其 mixed)的最佳聚合是否达到 8 GB/s 阈值,据此决定该目录是否适合承载 KV 缓存 I/O;
  3. 结合业务调整阈值:如果模型与负载对带宽有更高要求,可通过--threshold、配置文件中的threshold_gb或--config覆盖矩阵(分片、worker、epochs、读写比)获得更贴近生产的数据;
  4. 服务启动后做端到端验证:预检通过 ≠ 缓存链路就绪,还需完成 外部缓存验证 中的"落盘 + 重启回放"闭环。

需要留意的是:precheck的判定标准(内核 5.10、CUDA ≥ 8.0、HDK > 25.2.0、shm ≥ 512 GiB、带宽 ≥ 8 GB/s)以当前仓库 precheck.defaults.json 与源码实现为准,均为可配置阈值,具体部署时应结合自身机型、模型规模与实际缓存介质综合判断。

  • 大模型
  • 人工智能
  • 缓存

【免费下载链接】unified-cache-management

Unified Cache Manager(推理记忆数据管理器),是一款以KV Cache为中心的推理加速套件,其融合了多类型缓存加速算法工具,分级管理并持久化推理过程中产生的KV Cache记忆数据,扩大推理上下文窗口,以实现高吞吐、低时延的推理体验,降低每Token推理成本。

项目地址:https://gitcode.com/ModelEngine/unified-cache-management
点击查看免费下载

相关推荐

上一篇:Cargo 帮助系统全解:`cargo help` 用法、子命令层级规则与 man 手册实现原理
下一篇:Windows驱动存储清理终极指南:DriverStoreExplorer完全使用教程

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进