如何用 benchmark_llm 对 tinygrad LLM 做离线 prefill 与 decode 吞吐基准测试
2026/9/12 16:31:04 网站建设 项目流程

如何用 benchmark_llm 对 tinygrad LLM 做离线 prefill 与 decode 吞吐基准测试

【免费下载链接】tinygradYou like pytorch? You like micrograd? You love tinygrad! ❤️项目地址: https://gitcode.com/GitHub_Trending/tiny/tinygrad

仓库里自带了一个现成的基准脚本 extra/benchmark_llm.py,它从本地路径加载一个 GGUF 模型,先用一段合成 token 序列做分块 prefill,再逐 token decode 固定数量,最后分别打印两个阶段的 tok/s。整个过程不访问网络、不需要真实文本 prompt,适合在改动编译选项或切换后端之后,快速对比同一模型在 prefill 和 decode 两条路径上的吞吐变化。本文围绕这个脚本给出从环境准备到读数的完整流程。

准备环境:安装 tinygrad 并确认设备

README.md 推荐的安装方式是从源码安装:

git clone https://github.com/tinygrad/tinygrad.git cd tinygrad python3 -m pip install -e .

如果只是想 clone 后直接运行脚本而暂时不安装,docs/tinygpu.md 中提到可以用PYTHONPATH=.代替安装步骤,例如PYTHONPATH=. python3 extra/benchmark_llm.py ...

安装完成后,用下面这条命令确认 tinygrad 实际选择的默认设备:

python3 -c "from tinygrad import Device; print(Device.DEFAULT)"

打印出设备名(如CPUCLCUDA等)即说明环境可用。之后运行基准时实际跑在哪个后端,就以此输出和DEV变量(见后文)为准。

运行脚本本身没有额外依赖安装步骤,但需要准备一个本地 GGUF 模型文件:--model是必填参数,extra/benchmark_llm.py 要求传入 "path to gguf model",即模型文件的本地路径。项目文档没有给出固定的模型下载地址,模型文件由读者自行准备,下文命令中的<your-model.gguf>均指你自己模型文件的路径,首次出现时说明,后文不再重复。

运行基准测试

最短主路径,全部使用脚本默认参数:

python3 extra/benchmark_llm.py --model <your-model.gguf>

脚本的完整参数(来自 extra/benchmark_llm.py 的 argparse 定义):

参数默认值用途
--model必填GGUF 模型文件路径
--max-context8192max context length
--prompt-tokens1024number of prompt tokens
--decode-tokens16number of tokens to decode
--chunk-size32chunk size for prefill

两个由模型加载逻辑决定的边界条件,改参数前需要知道(来自 tinygrad/llm/model.py 中Transformer.from_ggufTransformer.generate):

  • --max-context会在加载时与 GGUF 元数据中的context_length取较小值,传得比模型本身支持更长也不会生效。
  • generate的循环条件是 token 总数达到max_context即停止,因此--prompt-tokens--decode-tokens的总量不要超过--max-context,否则请求的 decode 数量跑不满。默认的 1024 + 16 远小于 8192,不受影响。

一次典型的参数化运行示例(把 prefill 长度和 chunk 一起放大,验证分块 prefill 的影响):

python3 extra/benchmark_llm.py --model <your-model.gguf> --prompt-tokens 4096 --chunk-size 128

输出结果怎么看

脚本按顺序打印四行,每一行对应一个阶段,这也是判断一次运行是否完整跑通的标准:

load <秒数>s warm <秒数>s prefill <tok/s> decode <tok/s> output <生成的 token 列表>

各行的含义(对照 extra/benchmark_llm.py 源码):

  • loadTransformer.from_gguf(args.model, args.max_context)加载模型耗时。
  • warmmodel.warmup()耗时。warmup的实现是跑两次generate([0])(见 tinygrad/llm/model.py),用于在正式计时前完成 JIT 编译等一次性开销,所以load/warm两行与后面的吞吐数字相互独立。
  • prefillprompt_tokens除以从model.generate启动到拿到第一个 token 的耗时。源码注释明确写了 "first token is time-to-first-token; counted as part of prefill",即首 token 延迟计入 prefill 统计。prefill 阶段按--chunk-size分块消费 prompt,--chunk-size改的就是这里。
  • decodedecode_tokens除以第一个 token 之后剩余--decode-tokens个 token 的生成耗时,行尾output是本次实际生成出的 token 序列。

需要强调离线性质的一点:prompt 不是真实文本,而是合成序列[257] + [1000+i%1000 for i in range(prompt_tokens-1)],即首 token 为 257,其后在 1000–1999 区间内循环取模。模型文件也从本地路径读取,因此脚本运行期间不需要网络,测得的是吞吐本身,与生成质量无关。对比不同配置时,只比较同一模型、同一参数下prefilldecode两个 tok/s 数值即可。

可选分支:切换后端与打开 DEBUG 观察

docs/env_vars.md 说明了DEVDEBUG两个环境变量,都可以直接加在基准命令前:

  • 指定后端:DEV用于选择设备、renderer 与架构,文档给出的解释示例包括AMD(use the AMD device)、CPU:LLVM(use the CPU device with the LLVM renderer)。例如在 CPU 上跑同一基准作为对照组:

    DEV=CPU:LLVM python3 extra/benchmark_llm.py --model <your-model.gguf>
  • 打开调试输出:DEBUG=2起提供每个 kernel 的计时、内存与带宽指标;DEBUG=4起额外打印生成的 kernel 代码。例如:

    DEBUG=2 python3 extra/benchmark_llm.py --model <your-model.gguf>

    当两次基准吞吐差异明显时,用DEBUG=2找出耗时集中在哪些 kernel,比只看总 tok/s 更容易定位改动的影响。

需要注意的限制

  • 权重默认按 float16 加载:from_gguf中当环境变量HALF非 0(默认 1)时,会把 state dict cast 成 float16。对比不同后端时这一点天然一致;如需保留原始 dtype,按源码可用HALF=0运行。
  • from_gguf的第三个参数realize默认取环境变量REALIZE(默认 0),决定是否在加载后立即 realize 全部参数(见 tinygrad/llm/model.py)。
  • 模型带循环状态块(SSM/hybrid 结构)且当前设备不支持对应的自定义 kernel 时,generate会把chunk_size强制降为 1,分块 prefill 退化为逐 token,此时--chunk-size不再生效(tinygrad/llm/model.py)。
  • 合成 prompt 决定了这套数字不能直接当作真实对话场景的首 token 延迟或解码速度,它只是同一口径下的相对吞吐基准。

【免费下载链接】tinygradYou like pytorch? You like micrograd? You love tinygrad! ❤️项目地址: https://gitcode.com/GitHub_Trending/tiny/tinygrad

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询