llmfit Hardware Profile 硬件档案完全指南:用一条 --profile 在任意机器上预估模型可运行性与吞吐
【免费下载链接】llmfitHundreds of models & providers. One command to find what runs on your hardware.项目地址: https://gitcode.com/GitHub_Trending/ll/llmfit
llmfit 的 Hardware Profile(硬件档案)是一个命名且带版本号的 JSON 机器描述文件:它刻画一台机器的总内存、内存是否为统一内存(unified memory),以及吞吐估算器需要的带宽与算力参数。通过
--profile传入它,所有分析命令就会针对"这台目标机器"而非你当前所坐的宿主机打分——这正是回答"某个模型在这台不存在的机器上跑多快"这类问题的官方方案。读完本文你将掌握:内置档案的即拿即用、为未发布硬件手写档案的完整流程,以及档案字段背后的源码级作用机制。
Hardware Profile 面向的应用场景非常具体:--memory/--ram/--cpu-cores只能修改容量类字段,而 tok/s 吞吐估算依赖的是内存带宽与 fp16 矩阵算力(见 llmfit-core/src/fit.rs 中CalcConfig的实现),这些都不是容量。当你需要评估"在别人的机器(或还没上市的硬件)上模型表现如何"时,单个字段覆盖无法给出可信答案,一份描述整台机器的档案才是可复现、可评审的方案。
数据文件与完整字段契约位于 llmfit-core/data/hardware/,面向用户的完整操作教程见 docs/cli.md → Hardware profiles。
快速上手:三条命令体验硬件档案
最直接的体验方式就是调用内置档案。llmfit hardware子命令组负责档案的查看与管理,--profile让所有分析命令改用指定机器打分:
llmfit hardware list llmfit hardware show ryzen-ai-max-plus-395 llmfit --profile ryzen-ai-max-plus-395 fit -n 10 llmfit --profile ryzen-ai-max-plus-395 plan openai/gpt-oss-120b llmfit --profile nvidia-rtx-4090 recommend --json llmfit --profile apple-m3-max-128gb info "Qwen/Qwen3-4B-MLX-4bit"上面四行llmfit --profile ...分别展示了fit(给出一批模型的匹配度排名)、plan(为单个模型制定运行计划)、recommend --json(以 JSON 输出推荐)与info四种典型用法。--profile同时支持两种传参形式:直接写档案名(如ryzen-ai-max-plus-395),或写一个文件路径(如./my-workstation.json),后者无需安装任何东西即可临时评测。
注意约束:--profile会整体替换--memory/--ram/--cpu-cores三个参数,并与三者互斥(profile 描述的是整台机器,而这三个参数只覆盖单个字段);无法解析的 profile 属于硬错误,而不是被静默忽略。
目录布局:schema 与 profile 文件的存放约定
llmfit-core/data/hardware/ schema.json JSON Schema(draft-07),每个 profile 必须满足 <name>.json 一个 profile;name 必须等于文件名(去掉 .json 后缀)本目录下每个.json文件即一份 profile,其name字段必须与文件主干名完全一致——llmfit-core/src/hwprofile.rs中的check_name_matches_stem(见 hwprofile.rs)会强制这一约束,因为一个"列在列表里的名字"却无法被选中是典型事故源。
一个关键设计是这些档案的分发机制:目录下所有 profile 由 llmfit-core/build.rs 在编译期聚合(embed_hardware_profiles()读取data/hardware下全部 JSON 并拼接成单个数组),经include_str!嵌入二进制(见 hwprofile.rs)。因此:
- 一份合并进仓库的档案会随下一个 release直接内置分发,按名字使用、无需任何下载;
- 用户不需要重新编译,只需把档案文件放进
llmfit hardware path打印出的目录即可加载。
llmfit hardware path # 例如 Linux 下 ~/.local/share/llmfit/hardware # 可用环境变量覆盖:LLMFIT_HARDWARE_PROFILES=/tmp/my-hw优先级规则清晰可测:用户目录中name与内置档案同名的用户档案优先(shadow 机制,见下文源码解析);LLMFIT_HARDWARE_PROFILES环境变量则用于整体改指向用户档案目录,其实现位于 hwprofile.rs 的user_profile_dir()——读取该变量,为空时才回退到 llmfit 的更新缓存目录下的hardware子目录。
字段说明:schema_version 1 的全部字段与作用对象
llmfit-core/data/hardware/schema.json 是每个档案必须满足的权威契约,且additionalProperties: false(即验证阶段拒绝一切未声明键)。各字段含义如下:
| 字段 | 是否必填 | 作用对象 |
|---|---|---|
schema_version | 是 | 必须为1 |
name | 是 | 必须等于文件主干名,符合[a-z0-9][a-z0-9._-]* |
match.gpu_name_contains | 否 | 仅作溯源用 —— llmfit 永远不会自动选择 profile |
hardware.total_ram_gb | 是 | SystemSpecs容量(统一内存时同时充当 VRAM) |
hardware.unified_memory | 是 | SystemSpecs::unified_memory |
hardware.gpu_memory_bandwidth_gbps | 否 | CalcConfig::gpu_bandwidth_gbps_override |
hardware.ddr_bandwidth_gbps | 否 | CalcConfig::ddr_bandwidth_gbps |
hardware.gpu_compute_tflops_fp16 | 否 | CalcConfig::gpu_compute_tflops_fp16(prefill/TTFT 阶段) |
estimation.efficiency | 否 | CalcConfig::efficiency |
estimation.run_mode_factors.* | 否 | CalcConfig::run_mode_factors(按模式生效,未设的键保持默认值) |
calibration[] | 否 | 在schema_version1 中仅被解析并校验,尚未参与计算 |
几点值得展开:
match字段是纯溯源性质("这份档案描述哪张 GPU"),代码注释明确说明:profile 永远不会被自动选中,因此错误的猜测不会悄悄替换掉正确的本机检测(见 hwprofile.rs)。用户必须显式--profile才会生效。calibration用于记录带来源的实测锚点(哪个模型、什么量化、什么运行模式、实测多少 tok/s、来源链接),让它们现在可以被评审、未来可被更高 schema 版本消费。它今天不改变任何估算——实测锚点一旦应用会改变该机器上的每一项估算,所以先以"可评审的数据"形式随档案发布。- 离散 GPU 档案不携带 VRAM 数值,因此 VRAM 保持宿主机检测值不变;统一内存档案则是完整描述:VRAM 跟随
total_ram_gb(两者本就是一个池子)。 - 范围约束在源码
validate()中统一用check_range执行(见 hwprofile.rs):total_ram_gb上限 16384 GB、带宽与 TFLOPS 上限 100000、efficiency上限 1、run_mode_factors各键上限 10,且所有数值必须是大于 0 的有限数。注释特别指出边界故意放宽——目的是拒绝会让估算失去意义的取值(0 带宽会把 roofline 除以到零、NaN 会污染每个分数),而不是去审查硬件是否"合理"。
标准格式:一份完整的示例档案
每个文件都要符合 schema.json。下面是涵盖全部可选区块的完整示例(对应仓库文档中的示例并保留原样语义):
{ "schema_version": 1, "name": "example-unified-256", "match": { "gpu_name_contains": "Radeon 8060S" }, "hardware": { "total_ram_gb": 128.0, "unified_memory": true, "gpu_memory_bandwidth_gbps": 256.0, "ddr_bandwidth_gbps": 256.0, "gpu_compute_tflops_fp16": 29.7 }, "estimation": { "efficiency": 0.6, "run_mode_factors": { "cpu_only": 0.25 } }, "calibration": [ { "model": "openai/gpt-oss-120b", "quant": "MXFP4", "run_mode": "gpu", "measured_tps": 50.0, "source": "issue #969" } ] }各区块要点:
hardware.gpu_compute_tflops_fp16决定 prefill / TTFT 估算;缺省时 prefill/TTFT 如实报告null而非猜测(见 apple-m3-max-128gb.json 的做法)。estimation.run_mode_factors的每个键都可选,未设置的运行模式沿用RunModeFactors默认值而不会被清零——apply_to_config的测试断言了这一点(见 hwprofile.rs)。calibration[].run_mode只接受五个枚举值:gpu、tensor_parallel、moe_offload、cpu_offload、cpu_only(与crate::fit::RunMode的 snake_case 一致),非法值会在校验时被拒绝。
容错加载与严格校验:如何保证拼写错误不会静默失效
这是 llmfit 档案机制最具设计巧思的一点:加载与校验采用两套标准。
- 加载时容忍未知键(
parse+validate):一份为更新版本 llmfit 编写的档案在旧版本上依然能加载使用(向前兼容)。HardwareProfile通过#[serde(flatten)]把不认识的键收进unknown映射而不是报错(见 hwprofile.rs),loader_tolerates_unknown_keys_but_strict_validation_rejects_them测试验证了future_top_level、hardware.npu_tops这类未来键可以被解析并逐层记录路径(见 hwprofile.rs)。 hardware validate走严格校验(validate_strict):在validate()之上追加"拒绝一切未识别键",把 typo 变成可见错误而不是一个悄悄什么都不做的字段:
llmfit hardware validate ./my-workstation.json # FAIL ./my-workstation.json: unknown key(s): hardware.gpu_bandwith_gbps上面的报错正是"拼错bandwidth"这一典型场景的反馈。选择器解析规则也值得留意:resolve()先判断选择器是否"像路径"(以.json结尾、含路径分隔符、或磁盘上确有此文件三者任一成立即视为路径),否则按档案名查找;未知名字的报错会列出当前全部可用档案(见 hwprofile.rs 及对应测试 resolve_rejects_an_unknown_name_and_lists_alternatives)。
内置档案一览:三个种子档案及其设计含义
仓库当前内置三个档案,覆盖了三种典型拓扑,是学习手写档案的最佳范本:
| 名称 | 内存 | 带宽 | 说明 |
|---|---|---|---|
ryzen-ai-max-plus-395 | 128 GB 统一内存 | 256 GB/s | Strix Halo APU:256-bit LPDDR5X-8000。Radeon 8060S,40 个 RDNA 3.5 CU @ ~2.9 GHz → 约 29.7 TFLOP/s(packed fp16)。 |
apple-m3-max-128gb | 128 GB 统一内存 | 400 GB/s | 40 核 GPU 的 M3 Max。fp16 matmul 吞吐刻意留空,因此 prefill/TTFT 报告null而不是猜测值。 |
nvidia-rtx-4090 | 64 GB 系统内存 | 1008 GB/s | 离散 Ada 卡:165.2 TFLOP/s(tensor、fp32 累加的 dense fp16)。ddr_bandwidth_gbps为双通道 DDR5-5600。 |
它们的 JSON 文件在 llmfit-core/data/hardware/ 下与 README、schema 平级:
- ryzen-ai-max-plus-395.json:
unified_memory: true,gpu_compute_tflops_fp16: 29.7,并携带一条gpt-oss-120bMXFP4 的实测校准记录(measured_tps: 50.0); - apple-m3-max-128gb.json:
total_ram_gb: 128.0、带宽 400 GB/s,没有gpu_compute_tflops_fp16键——这是"缺省即如实报 null"的官方示例; - nvidia-rtx-4090.json:
unified_memory: false、GPU 带宽 1008 GB/s、ddr_bandwidth_gbps: 89.6、算力 165.2 TFLOP/s,且不带 VRAM 字段(VRAM 保持宿主机检测值)。
从三种档案可以看出字段与机器拓扑的对应关系:统一内存机器(APU / Apple Silicon)由total_ram_gb同时决定容量与显存池;离散 GPU 机器则分离系统内存与 GPU,估算 decode 走 GPU 带宽、CPU/offload 路径走ddr_bandwidth_gbps。
运行时如何应用档案:SystemSpecs 与 CalcConfig 的双轨联动
档案在运行时的应用不是一次性赋值,而是"规格 + 估算配置"双轨同步,保证描述整台机器的档案在内部自洽。核心逻辑在HardwareProfile::apply()(见 hwprofile.rs):
pub fn apply(&self, specs: SystemSpecs, config: &mut CalcConfig) -> SystemSpecs { self.apply_to_config(config); self.apply_to_specs(specs) }两条轨道的职责分别是:
apply_to_specs(容量侧):调用SystemSpecs::with_profile_capacity(见 hardware.rs)。实现细节里有一个严谨的自洽处理:先设置unified_memory再做 RAM 覆盖,保证统一内存档案让 VRAM 严格跟随total_ram_gb;若统一内存档案作用于一台没检测到 GPU 的主机,还会像--memory一样合成一块 GPU(否则所有模型都会掉进 CPU-only 路径,档案永远无法复现它所命名的机器);非统一档案则不携带 VRAM 值,保持检测值不动。apply_to_config(速度侧):逐项把gpu_memory_bandwidth_gbps→CalcConfig::gpu_bandwidth_gbps_override、ddr_bandwidth_gbps→CalcConfig::ddr_bandwidth_gbps、gpu_compute_tflops_fp16→CalcConfig::gpu_compute_tflops_fp16、efficiency与run_mode_factors各自映射到位。未设置的字段保持原样,让不完整的档案继续使用计算出的默认值(见 hwprofile.rs,测试 partial_profile_leaves_estimator_defaults_alone 断言最小档案不会改动任何估算默认值)。
档案目录的扫描逻辑(catalog_in)同样值得了解(见 hwprofile.rs):先装载全部内置档案,再扫描用户目录下的.json;用户档案会retain掉同名内置档案后插入,即同名用户档案替换内置档案而不是并列两份;加载失败的文件不会静默跳过,而是进入errors列表随目录一起上报——用户写的档案选不中是需要看到的 bug。
实战:为未发布硬件写一份自己的档案
你不必真的拥有那台机器。写一份档案、校验、然后对模型打分即可。以文档中的 M5 Ultra 场景为例:
第 1 步查看用户档案目录:
llmfit hardware path # 例如 ~/.local/share/llmfit/hardware # 覆盖方式:LLMFIT_HARDWARE_PROFILES=/tmp/my-hw第 2 步写档案(文件主干名必须等于"name"):
mkdir -p "$(llmfit hardware path)" cat > "$(llmfit hardware path)/m5ultra512.json" <<'EOF' { "schema_version": 1, "name": "m5ultra512", "match": { "gpu_name_contains": "M5 Ultra" }, "hardware": { "total_ram_gb": 512.0, "unified_memory": true, "gpu_memory_bandwidth_gbps": 1200.0, "ddr_bandwidth_gbps": 1200.0 } } EOF或者保留一份一次性文件、直接传路径,无需任何安装:
llmfit --profile ./m5ultra512.json fit --json第 3 步校验、列出、检视:
llmfit hardware validate "$(llmfit hardware path)/m5ultra512.json" llmfit hardware list llmfit hardware show m5ultra512第 4 步像拥有那台机器一样打分:
llmfit --profile m5ultra512 fit -n 20 llmfit --profile m5ultra512 plan --quant Q4_K_M openai/gpt-oss-120b llmfit --profile m5ultra512 recommend --json对应字段的影响总结(与本文字段表一一对应):
| 字段 | 效果 |
|---|---|
total_ram_gb | 容量(unified_memory为 true 时同时充当 VRAM) |
unified_memory | 统一内存池(Apple / APU)vs 离散 GPU |
gpu_memory_bandwidth_gbps | decode / 估算 tok/s |
ddr_bandwidth_gbps | CPU / offload 路径 |
gpu_compute_tflops_fp16 | prefill / TTFT;缺省 → 如实报null |
档案管理命令与已知限制
档案相关的全部管理命令:
llmfit hardware list # 内置 + 用户档案 llmfit hardware list --json llmfit hardware show <NAME> # 显示字段 + 在本机应用后会改变什么 llmfit hardware validate <file> llmfit hardware path已知限制(当前实现明确声明):
calibration[]目前仅存储供评审,不参与估算(schema v1);--profile暂时不能与--force-runtime组合使用;doctor命令拒绝--profile(它诊断的是当前宿主机),这种情况请改用hardware show查看档案应用效果。
质量保障:CI 级校验如何拦截损坏档案
内置档案在编译期被嵌入,而加载时无效文件会被直接丢弃——若无测试把关,一份格式错误的贡献就会以"永远选不中的档案"形式发布且构建不报错。仓库为此设置了双重防线:
- 集成测试 llmfit-core/tests/hardware_profiles.rs 用 jsonschema 校验器把
data/hardware/下每个.json(排除 schema 自身)逐一对照 schema.json 验证,并检查name与文件主干一致; cargo test -p llmfit-core会运行这些校验,同时在 hwprofile.rs 单元测试层断言embedded()中的内置档案全部通过validate_strict()(见 embedded_profiles_are_present_and_valid),且覆盖了wrong_schema_version_is_rejected、invalid_names_are_rejected、non_finite_and_out_of_range_numbers_are_rejected、calibration_is_validated_even_though_it_is_not_applied、unified_profile_makes_vram_track_ram_and_synthesizes_a_gpu、discrete_profile_sets_ram_and_leaves_detected_vram等关键行为。
因此一份格式错误的档案贡献会在 CI 失败而不是进入发布——社区提交硬件档案的完整闭环为:修改data/hardware/→cargo test -p llmfit-core通过 → 合并后经 build.rs 随下一 release 内置分发给所有用户。若想进一步把档案用于完整实操(如结合plan与recommend子命令、JSON 输出、TUI 中的估算配置),继续阅读 docs/cli.md 中从--memory/--ram/--cpu-cores单字段覆盖到硬件档案的完整链路即可。
【免费下载链接】llmfitHundreds of models & providers. One command to find what runs on your hardware.项目地址: https://gitcode.com/GitHub_Trending/ll/llmfit
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考