资讯详情

FreeToken MoE 离线推理基准完全指南:解码吞吐、权重加载与缓存拷贝的测量原理与实战用法

📅 2026/11/2 1:19:01 | 华诺云谱 👁 阅读
FreeToken MoE 离线推理基准完全指南:解码吞吐、权重加载与缓存拷贝的测量原理与实战用法
FreeToken MoE 离线推理基准完全指南解码吞吐、权重加载与缓存拷贝的测量原理与实战用法本指南以仓库 benchmarks 目录下的三个基准脚本为主线系统讲解 FreeToken 如何测量 MoEMixture-of-Experts模型在 offload / cpu / hybrid 三种后端下的端到端解码吞吐、专家权重加载速度与逐层缓存拷贝成本并介绍配套的ft bench bw带宽测试与后端自动选择机制。读完本文你将掌握每个基准脚本的测量原理、全部命令行参数与输出字段的含义并能在自己的机器上复现这些测量、利用结果指导 offload 缓存容量与 hybrid 取数策略的调优。一、基准体系概览四个工具的分工FreeToken 的 MoE 离线推理性能基准由四个互相配合的工具构成它们分别回答不同层面的性能问题工具脚本 / 命令测量对象是否需要 checkpoint端到端解码吞吐bench_decode_moe.pybs1 流式解码 tok/s含完整 serving 路径是权重加载时间bench_load_weight_generic.pyexpert-bank 从磁盘读入主机内存的时间是缓存拷贝成本bench_offload_cache_copy.py每层解码ensure_expertscopy_missing的拷贝耗时否合成数据带宽与后端选择ft bench bwbenchbw.py主机 RAM / PCIe 带宽生成引擎读取的 JSON 档案否它们的共同运行约定是从仓库根目录执行设置PYTHONPATHpython:.并固定到单张 GPUCUDA_VISIBLE_DEVICES0。每个脚本的--help与模块 docstring 都包含完整的细节说明。在深入各个脚本之前先明确这些基准所处的架构背景FreeToken 将 MoE 专家权重以专家库expert banks的形式驻留在主机内存pinned memoryGPU 上只保留一个统一的专家槽缓存slot cache。解码时命中的专家从槽缓存直接计算未命中的专家通过 PCIe 拷入缓存copy_missing或者交给 CPU 执行器计算——这正是 offload / cpu / hybrid 三种策略的差异所在。因此解码吞吐、加载速度和拷贝成本构成了这条离线推理链路最核心的三个性能维度。二、bench_decode_moe.py真实 serving 路径下的单流解码吞吐2.1 测量思路客户端视角而非引擎视角bench_decode_moe.py 测量的是已经部署好的 MoE 模型在单请求bs1下的解码 tok/s。它不走引擎内部接口而是对每个后端实际拉起一个ft serve进程向/v1/chat/completions发送带streamtrue的请求并逐事件打时间戳。因此数字天然包含调度器scheduler、去分词器detokenizer和 HTTP/SSE 一跳的完整开销——即客户端真实感知的吞吐而非裸引擎 forward 的数值。在 bs1 下服务端每个解码步发出一个 delta 事件最后一个 chunkstream_options.include_usage带有精确的 token 计数于是吞吐按下式计算decode_tok_s (completion_tokens - 1) / (t_last_event - t_first_event)这个公式即使去分词器把多个 token 合并进一个事件如多字节字符也依然正确因为窗口锚定在第一个与最后一个 token 的到达时刻。ignore_eosTrue保证步数精确等于设定的D不受采样影响。TTFT 是本次测量中热机后的首个 token 延迟含模板渲染与 prefill。需要说明的是引擎内部诊断信息如 expert 缓存 miss rate、hybrid 取数拆分不会通过 API 暴露因此该脚本不报告这些指标VRAM 取的是服务端/v1/stats的实时值。2.2 命令行参数参数默认值说明--model必填checkpoint 目录或.ftw--backendoffload逗号分隔的offload\|cpu\|hybrid每个后端一个独立服务进程--aime$FREETOKEN_AIME25_JSONL本地 jsonl 文件替代从 Hub 下载 AIME-25 数据集--problem00 起始的 AIME 题目索引--decode256要测量的解码 token 数D--cache0GPU 专家槽数0 根据空闲 VRAM 自动定容--cache-rateNone缓存槽数取 L×E 的比例--cache的互斥替代--hybrid-fetch-1hybrid 后端每层最大 PCIe 取数-1 自动按实测 pcie/cpu 带宽比例--mem-ratio0.9目标 VRAM 利用率--gpuNone服务所用 GPUUUID 或 nvidia-smi 索引同ft serve --gpu--no-graphFalse关闭 CUDA graph改用 eager 解码--greedyFalse强制 temperature 0忽略 checkpoint 采样使 token id 可跨后端比较--server-timeout1800等待服务就绪的秒数--jsonNone把结果行追加到指定 JSON 文件JSONL2.3 提示词与采样保证路由代表性提示词选用AIME-25 竞赛题以聊天消息形式发送并开启 thinking——这是一个真实的推理负载专家路由因此具有代表性。题目默认从 Hub 上的math-ai/aime25数据集test.jsonl下载到常规 HF 缓存首次运行触发--aime可指向本地 jsonl。load_problem()同时兼容 Hub 的problem字段与本地已预格式化 jsonl 的prompt字段若文本中没有\boxed{}会自动追加Please reason step by step, and put your final answer within \boxed{}.指令——boxed 答案也便于肉眼抽查结果。采样参数优先采用 checkpoint 的generation_config.json推荐值未指定的字段回退到FALLBACK_SAMPLING {temperature: 1.0, top_p: 0.95, top_k: 64}见脚本 L61-L71。为什么要在客户端解析并显式发送因为服务端对未指定字段的默认是贪婪解码temperature 0、无过滤会让没有完整采样建议的 checkpoint 在推理负载下悄悄降级。resolve_sampling()还会处理两个边界do_sampleFalse或temperature0.0时返回贪婪参数HF 用top_k0表示不过滤而 API 用-1需要换算L143-L162。--greedy则强制 temperature 0 / top_p 1.0 / top_k -1用于更严格的跨后端对比。2.4 服务端启动参数映射每个后端由脚本以子进程拉起ft serveserve_cmd()关键映射如下--moe-backend backend指定 offload / cpu / hybrid--max-running-requests 1保证单流--max-seq-len-override 8192D为提示词与 D 个解码 token 留足序列长度--memory-ratio mem_ratio目标 VRAM 利用率--cuda-graph-max-bs 1--no-graph时为0解码走 CUDA graph--moe-hybrid-max-fetch hybrid_fetchhybrid 取数上限缓存容量三选一--moe-cache-size--cache 0、--moe-cache-rate--cache-rate指定、--moe-cache-auto默认。脚本先轮询/health直到maintenance serving再查询/v1/models拿到 model id然后执行两次stream_generate()第一次用于把 expert 缓存热到稳态解码工作集第二次才是被测量的请求。2.5 输出字段与跨后端校验每个后端生成一行结果关键字段包括decode_tok_s解码吞吐、ms_per_token、event_ms_p50/p99SSE 事件间隔分位数、ttft_ms热 TTFT、prompt_tokens、vram_gib、output_sha1输出文本前 12 位哈希等L350-L367。output_sha1是跨后端一致性检查非贪婪模式下每个服务进程内是确定性的全新服务 固定请求序列因此同模型三个后端应产生相同哈希。不过 token id 不通过 API 暴露这是比旧版进程内 id 哈希更弱的约束脚本 docstring 中明确说明。--json out.json将每行结果以 JSONL 追加便于批量对比。若指定多个后端单个后端失败包括解码中途服务崩溃导致的连接断开不会中止其余后端脚本会记录失败列表并最终以非零退出码返回每个后端结束后通过SIGTERM90 秒宽限再SIGKILL30 秒整组进程并额外 sleep 3 秒等待驱动回收 VRAM避免污染下一个后端的测量stop_server()。# 单个后端 CUDA_VISIBLE_DEVICES0 PYTHONPATHpython:. python benchmarks/bench_decode_moe.py \ --model /path/to/model # 三个后端各起一个服务结果写入 JSON ... --model /path/to/model --backend offload,cpu,hybrid --json out.json三、bench_load_weight_generic.py专家库加载时间对比3.1 三种加载模式bench_load_weight_generic.py 测量 MoE 启动阶段的主导成本——把离线专家库从磁盘读入主机内存——并对比三种方式baseline串行load_expert_banks(...)默认串行加载器scattered read pinparallel并行 O_DIRECTload_expert_banks(..., parallelTrue)对原始 checkpoint做分块多线程 O_DIRECT 读取无需重打包ftw一次性把模型转换为 FTWFreeToken 统一的整模型格式含稠密权重与专家之后从重打包后的 FTW 读取内部走 load_ftw_banks转换构建成本单独报告。三种模式都走框架真实的load_expert_banks代码路径没有脚本内自实现的读取器且返回相同的ExpertBanks.sources校验和必须与 baseline 一致。该基准是 Linux-onlyFTW 默认暂存在/var/tmp/ftw_模型名--ftw-dir可覆盖体积约为 checkpoint 大小放在/var/tmp是因为磁盘空间大且不受/tmp清理器清扫目录按模型名隔离避免不同模型并发基准相互覆盖。3.2 关键设计子进程隔离与冷读保证每个模式跑在独立的子进程中这样其约一个 bank 大小的 pinned 内存会在下一个模式开始前被回收——两套完整 bank 同时驻留会导致 OOM。每个 worker 通过 stdout 输出RESULT前缀的 JSON 行stderr 继承终端以便 tqdm 进度条与 INFO 日志实时可见L239-L254。默认情况下每个模式在读取前先用fadvise DONTNEED驱逐页缓存_evict_cache()无需 root确保每次读取测的是真实磁盘——否则 baseline 的 mmap 会命中热缓存显得虚快。--no-drop-cache可关闭驱逐以做热缓存对比。内存指标由后台MemSampler线程采样进程峰值 RSS读/proc/self/status的 VmRSS与系统MemAvailable最低水位读/proc/meminfo。3.3 校验和位置加权采样哈希_checksum()对每个 bank 以全局字节偏移加权采样约 100 万字节并折叠进哈希L103-L133。加权是必要的普通求和是置换不变的而并行 / FTW 读取器恰恰可能在专家重排上出错。偏移跨每层张量全局连续因此哈希与 bank 的切分方式无关一个扁平[L*E, ...]张量还是逐层列表且计算时不物化拼接副本不会抬高本基准报告的峰值 RSS。脚本 docstring 也坦承这是抽样而非证明此规模下跨步达数十 KiB小于该跨步的局部损坏可能漏检。3.4 命令行参数与结果表格参数默认值说明--model必填原始 checkpoint 路径--modesparallel,ftw逗号分隔的待测模式baseline 总是作为参考先跑--workers8并行读取线程数--chunk-mib8并行读取的分块大小MiB--shard-gib8.0FTW 构建的 shard 大小上限GiB--ftw-dirFTW 暂存目录默认/var/tmp/ftw_model--no-drop-cacheFalse不驱逐页缓存热比较--keep-ftwFalse跨次运行保留并复用已转换的 FTW 目录--gpu首块可见 GPUGPU UUID 或 nvidia-smi 索引结果输出为一张对比表mode / load_s / read GiB/s / peakRSS / speedup / bytes。speedup 相对 baseline 计算每个非 baseline 行的 checksum 与 baseline 比较不一致标记为BAD并最终以非零退出码结束——保证脚本化运行或 CI不会把字节不一致当作成功。--keep-ftw未指定时结束时 FTW 目录会被删除。PYTHONPATHpython:. python benchmarks/bench_load_weight_generic.py --model /path/to/model ... --modes parallel,ftw # 子集模式baseline 始终作为参考 ... --keep-ftw # 跨次运行保留转换后的 FTW3.5 底层加载器逻辑load_expert_banks的实现在 python/freetoken/moe/expert_banks.py#L275-L368它提供两条路径FTW 快速路径若model_path是已转换的 FTW checkpoint直接连续分块 O_DIRECT 读取重打包后的 banks不做自动转换慢速路径原始 checkpoint自动选择parallel当专家以小张量散存时串行读取很慢该判断来自experts_scattered()或serial专家已打包时串行即可饱和并行只会带来读放大。parallelNone表示自动选择生产默认True/False强制指定供本基准与转换器使用。并行读取器在低内存机器上会因额外的整 shard 匿名缓冲而 OOM因此自动模式还会检查空闲内存是否足以覆盖 banks 加一个 shard 的瞬时占用不足则回退串行--expert-load serial/parallel可强制。四、bench_offload_cache_copy.py合成数据下的逐层解码拷贝成本4.1 目的聚焦拷贝路径本身bench_offload_cache_copy.py 不需要任何 checkpoint——它用合成张量直接驱动 MoE 缓存的真实内核测量每层解码的完整移动成本ensure_expertsLRU 槽重映射 逐 bank 的fast_index_copy_jitgather。它把 batch size 与 miss rate 作为变量扫描tok_ms列把单层拷贝成本外推到整个模型——假设所有 MoE 层具有相同的 miss profile。CUDA_VISIBLE_DEVICES0 PYTHONPATHpython:. python benchmarks/bench_offload_cache_copy.py4.2 模型档案与 bank 布局脚本内置一组模型档案L36-L50覆盖多种量化格式与几何形状档案层数 L专家数 Etop-k量化格式H / Iqwen3.5-35B402568bf162048 / 512qwen3-30B481288bf162048 / 768gemma4-26B301288bf162816 / 704minimax-m2.5-marlin622568nvfp4_marlin3072 / 1536minimax-m2.5-triton622568nvfp43072 / 1536glm4.7-nvfp4891608nvfp45120 / 1536gpt-oss-20b24324mxfp4_triton2880 / 2880gpt-oss-120b361284mxfp4_triton2880 / 2880每个档案的逐 bank 形状由量化格式的 bank schema 推导bank_specs()schema 的唯一权威定义在 offload_cache.py 的_BANK_SCHEMAS例如 bf16 是(gate_up, down)两个 banknvfp4 是六个 bankpacked 码 每 16 块 e4m3 scale 每输出行 fp16 globalmxfp4_triton 是六个转置 bank_blocks/_scales/_bias。缓存机制本身与布局无关只负责搬行——这正是脚本可以按 schema 合成任意格式张量的原因。4.3 状态准备与计时方法prepare_state()构造每个槽都归其他层所有的初始状态id 空间是扁平的id layer_id * num_experts expert保证驱逐要做真实工作而本层从不命中。miss 数按active_unique × miss_rate取整其中active_unique min(E, batch_size × topk)。计时用 CUDA event 夹住ensure_expertscopy_missing每档重复 25 次取中位数--repeat。4.4 参数与输出参数默认值说明--gpu首块可见 GPUGPU UUID 或 nvidia-smi 索引--repeat25每档重复次数取中位数--models全部档案待测档案名列表--cache-slots[E, 0.4·L·E]绝对槽数默认两档单层专家数 E以及 0.4×L×E 的目标场景--batch-sizes[1, 4, 16, 32]批量大小扫描--miss-rates[0.0, 0.25, 0.5, 1.0]miss rate 扫描每档输出一行bs / active / miss_rate / misses / time_ms / copy_MiB / bw_GBps / tok_ms其中copy_MiB misses × 每专家字节数bw_GBps是拷贝带宽tok_ms time_ms × L外推整个模型每个解码 token 的拷贝成本。值得注意的是脚本仅实际驱动LAYER_ID0但缓存接线完全按真实契约每个 bank 的bank_sources是逐层张量列表只填充索引 0因此测到的是真实内核路径。底层对应OffloadMoeCachepython/freetoken/moe/offload_cache.py的ensure_experts与copy_missing拷贝还可通过环境变量FREETOKEN_FUSED_COPY0强制关闭多 bank 融合拷贝走逐 bank 旧路径做 A/B 对比。五、ft bench bw主机带宽测量与 offload / hybrid 后端决策5.1 为什么需要它解码 miss 时专家走 PCIeoffload 路径还是 CPU 计算hybrid 路径是一个带宽主导的决策。ft bench bwpython/freetoken/moe/benchbw.py在本机实测两条路径的真实带宽并把结果写成 JSON 档案供引擎读取从而在--moe-strategy auto下自动选择后端、并为 hybrid 设定取数拆分比例。5.2 两层测量上限测量纯硬件、与模型无关STREAM 风格的 CPU DRAM 读取以及线性 pinned↔device 拷贝给出快速上界真实内核测量按工作负载 专家 dtype实际 CPU MoE GEMVCpuMoeExecutor即 hybrid 在 CPU 上计算的内容与实际 PCIe gatherOffloadMoeCache.copy_missing/fast_index_copy即 offload 在解码 miss 时流式传输的内容。两者都可用时还会重叠测量并发运行、争抢主机 DRAM这两条达成带宽即设定 hybrid 的逐步取数拆分load_hybrid_fetch_fraction。决策规则按工作负载, 格式当 CPU MoE 内核带宽超过threshold倍默认 2x的 PCIe gather 带宽时推荐hybrid否则offload。没有 CPU MoE 权重路径的格式如 block-fp8无法在 CPU 上计算恒定为offload。5.3 用法与输出ft bench bw # 默认全部格式的 per-dtype 调优基准 ft bench bw --dtype nvfp4,bf16 # 只测这些格式 ft bench bw --model qwen3.6-moe # 改为按模型几何测量 ft bench bw --dtype all --model all # 两者都做 ft bench bw --gpu GPU-2f3a... # 指定 GPUUUID 或 nvidia-smi 索引结果写入每 GPU 一个的 JSON 档案默认路径$XDG_CACHE_HOME/freetoken/benchbw/gpu-uuid.json多 GPU 机器每卡一份旧版无 uuid 的benchbw.json亦被兼容。读取侧是无 torch 依赖的 bench_profile.py引擎通过它加载档案。ft bench bw还支持--dtype/--model/--threshold等参数透传daemon 的/benchmark/start端点也会在引擎主机上运行它以生成档案见 daemon/app.py。相关 CLI 入口在 cli.py。5.4 档案如何驱动引擎配置引擎在 engine/config.py 与 engine.py 中消费该档案moe_strategyauto将 MoE 模型解析到 offload 家族当ft bench bw档案推荐 hybrid 时采用 hybridresident 的fused专家则必须显式请求server/args.py 的 --moe-strategy--moe-hybrid-max-fetch -1默认时每步按档案中实测的 pcie_bw/cpu_bw 比例取数理想重叠要求PCIe 取数专家数 : CPU 计算专家数 pcie_bw : (cpu_bw - pcie_bw)engine.py L747-L764没有可用档案时回退到固定上限 1缓存的档案还可以把配置从 offload 升级到 hybridengine.py L1617-L1659前提是 CPU MoE 执行器可用。此外offload_cache.py 中的 hybrid 字段hybrid_max_fetch、hybrid_fetch_fraction正是上述决策在运行时的落点ensure_experts_hybrid只给本步最多hybrid_max_fetch个 miss 专家分配槽位并调度拷贝溢出部分改写为-1交给 CPU 执行器num_indices与num_missing_full分别记录取数上限内与未封顶的 miss 数供统计。六、组合使用建议四个工具正好覆盖运行前、启动时、解码中三个性能阶段可串成一条完整的调优流水线先用ft bench bw建立本机带宽基线结果写入每 GPU 的 JSON 档案后--moe-strategy auto即可自动决定 offload / hybrid并让--moe-hybrid-max-fetch -1得到正确的取数比例用bench_load_weight_generic.py评估启动成本对比串行、并行 O_DIRECT 与 FTW 三种加载路径若 FTW 明显更快且可接受一次性转换开销--keep-ftw复用可考虑在生产中以 FTW 格式存放模型校验和机制保证任何重排错误都会被当场捕获用bench_offload_cache_copy.py选缓存容量与理解拷贝瓶颈不需要 checkpoint 即可扫描 batch size × miss rate × 槽数组合tok_ms直接给出 miss 对单 token 延迟的贡献指导--moe-cache-size/--moe-cache-rate的取舍默认槽数E与0.4·L·E两档即是轻量级与目标场景的代表最后用bench_decode_moe.py做端到端验收对每个后端起真实服务、以 AIME-25 推理负载测量客户端可见的 tok/s 与 TTFT--json落盘、output_sha1校验跨后端一致性--greedy可做更严格的对照。需要提醒的边界条件加载基准仅限 Linux依赖 O_DIRECT 与 fadvisebench_decode_moe.py的 AIME 数据首次运行需联网下载可用--aime指向本地 jsonl 规避bench_offload_cache_copy.py与ft bench bw需要可用 CUDA 设备。所有基准都应固定 GPU 并确保无人共享该卡否则吞吐与带宽数字不具备可比性。创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑