colibri Vulkan 计算后端完全指南:在任意 Vulkan 1.2 GPU 上运行 GLM 解码 colibri Vulkan 计算后端完全指南在任意 Vulkan 1.2 GPU 上运行 GLM 解码【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 项目地址: https://gitcode.com/GitHub_Trending/colibri3/colibricolibri 内置了可选的 Vulkan compute 后端能够在任何被 Vulkan 驱动可见的 GPU 上运行完整的 GLM 解码计算路径——不需要 CUDA也不需要 ROCm。本文以 docs/vulkan.md 为主体结合仓库源码与测试系统讲解该后端的构建方法、环境变量、GPU 上执行的部件划分、正确性验证、实测性能、跨后端对比陷阱与已知限制帮助你在被厂商堆栈放弃的旧卡、AMD 新卡或 APU 上榨出可用的推理性能。快速上手构建与运行Vulkan 后端是**可选opt-in**特性默认构建完全不受影响。构建命令在c/目录下执行cd c make glm VK1 # needs libvulkan glslc (shaderc) for the shaders在 c/Makefile 中VK1会追加-DCOLI_VULKAN编译宏与-lvulkan链接选项并把四份 GLSL 着色器编译产物纳入构建VK ? 0 GLSLC ? glslc ifeq ($(VK),1) CFLAGS -DCOLI_VULKAN LDFLAGS -lvulkan VK_OBJ backend_vulkan.o VK_SPV shaders/qmatmul.spv shaders/qmatmul_gate_up.spv shaders/attention_absorb.spv shaders/rmsnorm.spv endif其中.spv由glslc --target-envvulkan1.2从同目录的.comp源码生成Makefile 规则构建时若找不到glslc会直接报错提示安装 shaderc。运行一个最简单的例子COLI_VULKAN1 COLI_VK_DENSE1 COLI_VK_ATTN1 \ PINmodel/.coli_usage PIN_GB0 COLI_NO_OMP_TUNE1 \ ./coli run Hello --topp 0.7环境要求运行时libvulkan以及一块提供 Vulkan1.2ICD 的 GPU驱动需支持GL_KHR_shader_subgroup_arithmetic扩展近几年的任意 Mesa RADV、AMDVLK、NVIDIA 或 Intel ANV 驱动均满足。构建时glslc来自 shaderc。后端会挑选能力最强的物理设备独立显卡优先于核显并且任何失败都会降级到 CPU 路径——一块卡死wedged的 GPU 最多拖慢运行速度绝不会损坏结果。别忘了 COLI_NO_OMP_TUNE1在多核机器上必须设置COLI_NO_OMP_TUNE1引擎的 OMP 自调优自旋等待在COLI_CUDA/COLI_METAL下会被跳过但在 Vulkan 下不会。自旋的工作线程会饿死异步 I/O 池——实测 CPU 专家带宽会从 28 GB/s 跌到 5 GB/s。独立显卡必须先开 Resizable BAR权重分层分配的是HOST_VISIBLE|DEVICE_LOCAL内存如果关闭 ReBAR这种组合只存在于约 256 MB 的 BAR 窗口内驱动会把超出部分静默放到系统内存里——于是分层报告专家已驻留但每次访问都在穿越 PCIe比 CPU 路径还慢。在 RX 9070 XT 上实测BIOS 开关两侧分别是 0.11 与 0.24 tok/s。引擎在初始化时如果发现 VRAM 的可主机访问切片偏小会打印警告看到该警告就去 BIOS 里开启 Resizable BAR / Smart Access Memory。统一内存unified-memory的 APU 不受影响。着色器查找路径编译好的着色器通过COLI_VK_SHADERS定位可以是qmatmul.spv文件本身也可以是存放整套.spv的目录未设置时引擎先找二进制旁的shaders/再找相对当前工作目录CWD的位置。注意 docs/ENVIRONMENT.md 的说明给出目录时其余着色器会在同一目录下按文件名被发现。GPU 上跑什么三块部件后端把解码路径按“驻留频率”划分成三块用三个环境变量独立开关部件环境变量机制路由专家热集COLI_VK_EXPERTSN默认 320按.coli_usage热度取 Top-N 专家启动时一次性上传到 VRAM 注册表解码时直接从 VRAM 提供不占 RAM 槽、不读磁盘、不预取以一次异步融合批次gateupsilu→down隐藏层留在设备上与 CPU 计算其余专家并行。命中率行中显示为vk桶。稠密投影COLI_VK_DENSE1q_akv_a 融合为一次提交q_b、o 各自成批共享专家作为单个融合专家组提交。驻留的 int4/int8 权重只上传一次。MLA 注意力核心COLI_VK_ATTN1每层一次 dispatch吸收式 queryabsorbed query、KV 窗口上的分数、softmax、加权潜变量、值行与 o 投影融合上下文向量从不离开 GPU。潜变量/rope KV 存放在持久化的逐层设备镜像中每 token 每层追加约 2.3 KB失效点与 CUDA KV 影子完全一致。示例命令中的PIN_GB0但保留PIN是有意为之VRAM 注册表里已经装着与 RAM pin 相同的热专家pin 的 RAM 应该留给自适应 LRU 缓存。保留PIN是为了防止 AUTOPIN 从历史记录里重新 pin。这些开关背后是 c/backend_vulkan.h 中的一组 API 契约coli_vk_matmul单个量化 GEMVfmt1为 int8、fmt2为 int4首次调用上传权重与 scale之后复用驻留副本coli_vk_gate_up专家 MLP 前半段silu(gate(x))*up(x)在一次 dispatch内完成x 只读一次coli_vk_expert_group/_issue/_take整批专家的融合 MLP 一次提交同步或异步隐藏层全程在设备上异步形态先下发再 join 读回CPU 与 GPU 重叠计算coli_vk_attention_absorb/_project吸收式 MLA 注意力核心以及融合 o 投影的变体coli_vk_attn_qprepq 预备链q_akv_a 对 → q 潜变量 rmsnorm → q_b在一次提交内完成需要rmsnorm.spvcoli_vk_alloc_priority/coli_vk_mem_budget借助VK_EXT_memory_priority/VK_EXT_memory_budget做 VRAM 压力防护——引擎把批量专家层填充的优先级压到 0.4使过载的堆优先逐出冷专家绝不动逐 token 的注意力工作集。着色器层面的实现细节c/shaders/qmatmul.comp 是解码 GEMV 的核心注释明确列出了借自 llama.cppmul_mat_vec的三项技术x[s,:]只加载一次到共享内存供工作组内每个输出行复用x 位于 host-visible 暂存区避免每次跨 BAR 重读一个 subgroup 对应一个输出行lane 以完全合并coalesced的方式跨过权重字用一次subgroupAdd取代屏障密集的共享内存树归约按行网格步进grid-stride固定且利于占用率的工作组数量可覆盖任意 O 与任意 subgroup 宽度RADV wave32/64。着色器还实现了多种量化格式int8、int4每字节 2 个、nibble−8、int3-g64每 64 输入一组、双平面打包、每组一个 f32 scale、分组 int4以及 Kimi K3 专家使用的MXFP4e2m1 nibble、bit3 为符号位scale 由宿主预展开为 f32每 32 输入一组。隐藏维上限 614424 KB LDS超过暂存数组长度的行如o_proj的I H*vh 16384会跳过共享内存暂存直接从存储缓冲读取。c/shaders/attention_absorb.comp 则演示了“单次 dispatch 跑完整注意力核”每个query 行 s, head h一个工作组吸收式 query、因果分数、softmax、潜变量上下文、值行读取全部在一次提交内完成L/R 直接读设备端持久缓存。共享内存数组的硬上限为 Q≤256、R≤64、K≤512。内存类型的两个写合并规则实测中能让这套设计成立的是两条内存规则见 c/backend_vulkan.c 中memtype/memtype_cached的选择CPU 要读回的缓冲必须是HOST_CACHED否则 ReBAR VRAM 读取只有约 40 MB/s其余一切使用HOST_VISIBLE|DEVICE_LOCAL——在 Strix Halo 这类统一内存平台上所谓“上传”写进的正是 iGPU 读取的同一块物理 RAM根本没有 PCIe 拷贝这正是流式专家在这里能盈利而离散 CUDA 路径刻意回避的原因。第二设备COLI_VK_DEV2后端还支持把专家层放到第二块 Vulkan GPU 上COLI_VK_DEV2可设为设备枚举索引或auto自动选择非 0 号设备的最强真实 GPU其上下文只承载层专家、只跑异步专家组路径可与 0 号设备同时在途backend_vulkan.h。tensor 会记住自己所在的设备free/bytes对两者皆可用。正确性如何在两个实现之间建立信任Vulkan 路径与 CPU 路径是同一乘法的两套独立实现唯一重要的是给出相同的 token一个解错 nibble、搞反分组方向或打乱 scale 顺序的 kernel 不会报错它只会给出一个变差的模型。因此验证策略是“比 token不比 logit”。1. 原语级精确性测试文档给出的命令gcc -O3 -DVK_TEST backend_vulkan.c -o test_vk -lvulkan -lm ./test_vk shaders/qmatmul.spv该测试覆盖每个原语不同形状下的 GEMV int4/int8含长行 o 投影、融合 gateup、完整专家组的同步与异步路径、matmul 对以及吸收式注意力核心含因果 S2、kv_start 窗口、int8 与长上下文。典型 maxrel 约 1e-5 到 2e-3fp32 归约顺序差异。2. 引擎级一致性贪婪解码在验证提示词上与纯 CPU 引擎逐 token 完全一致。3. 权重布局零重打包int4 权重以偏移二进制nibble−8解码与 CPU 路径的字节级布局完全一致无需重新打包。仓库里还有自动化回归测试 c/tests/test_glm53_vulkan.py它用同一 fixture 分别以纯 CPU 与COLI_VULKAN1运行引擎各 4 个贪婪 token比较两者的输出当二进制未以VK1构建或没有可用设备时测试声明为SKIP而非假绿色。运行方式make VK1 glm53 python3 tests/test_glm53_vulkan.py --binary ./glm53 --fixture ~/glm53_mm_tiny实测性能AMD RX 9070RDNA4RADV/Mesa 26.1文档给出的数据全部来自同一张 RX 9070 卡RADV/Mesa 26.1指标Vulkan对比对象专家 MLP 原语K 个专家int4 6144→2048→6144含回读0.11–0.13 ms/专家生产 ROCm/HIP 专家组0.179 ms/专家快约 35%解码 MLA 注意力核心3.7×快于同卡 HIP kernel—端到端 GLM-5.2744B int4NVMe 流式12 核 Zen2 RX 90701.7–1.8 tok/s64-token/ 1.6256-token/1.58 持续512-tokenHIP 后端同配置 1.5–1.55其中“每调用含回读”意味着 0.11–0.13 ms 已经算上数据从设备回到 CPU 的开销。需要强调的是端到端 tok/s 取决于整机还有什么在拖后腿磁盘带宽、CPU 侧专家计算等原语快 35% 不等于端到端同比例提升。与其他后端对比时的两个坑文档特别警告有两个默认行为会静默扭曲任何 Vulkan 对 CUDA/HIP 的对比MTP 投机解码CUDA/HIP 构建默认禁用模型草稿DRAFT在COLI_CUDA1下自动解析为 0见 issue #163而 CPU 与 Vulkan 运行保持DRAFT3。于是两组对照跑的是不同的解码循环——投机分支每个产出 token 要路由约 2× 的专家位置被拒绝的草稿位置仍然付出专家 I/O这在存储受限的机器上起主导作用。两边输出其实完全一致贪婪验证无损所以看起来没有任何异常。必须在两个分支上显式钉住DRAFT0或DRAFT3 COLI_CUDA_MTP1。GPU 时钟解码 dispatch 是微秒级突发本身不足以让 DPM 提频显存时钟可能整场运行都停在低位。两个分支都要钉住power_dpm_force_performance_levelhigh或者在结果中如实披露时钟状态。另外注意运行统计里的experts loaded/token统计的是路由位置数含被拒绝的投机位置在咨询任何缓存/分层之前计数——VK 层命中时它不会下降命中率行里的vk桶才是衡量分层有效性的数字。环境变量速查除文档正文外docs/ENVIRONMENT.md 收录了完整的 Vulkan 相关变量补充若干重要项COLI_VK_DEV指定主 Vulkan 物理设备枚举索引未设置时优先独立显卡。COLI_VK_QPREP默认开把 Q 预备步RMSNorm rope compress融合为一次 GPU dispatch 而不是拆开拆开会付出三个 fence 的代价2额外保留 CPU 参考副本用于 A/B 对比。COLI_VK_RESERVE_GB默认 3.0为惰性分配的稠密权重、KV 镜像与暂存缓冲预留的 VRAM4k 上下文实测约 1.7 GB随max_t增长。仅在驱动报告VK_EXT_memory_budget时有意义否则只受COLI_VK_EXPERTS数量上限约束。COLI_VK_SPIN_US默认 300轮询 fence 的微秒数0表示总是阻塞空闲时延迟更低代价是一个核心空转。COLI_VK_EXPERTS2/COLI_VK_RESERVE2_GBdev2 层的专家数上限与保留 VRAM。VK_PROF设置后计时并上报 Vulkan 专家组路径。Kimi K3 模型另有两个变量K3_VK_GBK3 专家层的 VRAM 上限默认取驱动预算与K3_VK_UP填层时每步允许的专家上传数默认 8。COLI_VK_TEST_BALLAST分配 N 个哑 Vulkan 缓冲以复现“VRAM 空闲时解码注意力仍随专家层规模退化”的现象——这是VK_EXT_memory_priority存在的理由实测 2.6k 缓冲对象 7.9s → 4.3k 时 15.6s且仍有 2.9 GB 空闲。从源码结构看backend_vulkan.c后端还维护了一个重提交缓存当绑定的 tensor/形状/暂存缓冲与上次调用一致时跳过vkUpdateDescriptorSets与命令重录——这正是热专家被反复调用的典型模式由于每次调用都会同步等待 fence不会有提交在途因此这种“仅在变化时重绑”是安全的。同一段代码也记录了注意力工作集KV 镜像、暂存借助 memory-priority 高于批量专家权重的设计依据实测驻留 7.6 GB 时解码注意力耗时 7.8s涨到 15.2 GB 时变成 17.8s。已知限制与未来工作解码聚焦专家层与注意力核心服务于S4prefill 使用 CPU/批处理路径稠密投影在 prefill 阶段可在 VK 上运行。回退到 CPU 注意力路径DSA top-k 选择、参差不齐ragged的多槽服务、以及量化 KV 缓存。尚未完成cooperative-matrixcoopmatprefill kernel、全驻留层流水线、在真实硬件上验证 Polaris/gfx803着色器使用动态 subgroup 大小按构造即 wave64 安全。小结Vulkan 后端让 colibri 的“tiny engine, immense model”理念第一次与硬件厂商无关无论是 ROCm 已放弃的 PolarisRX 580 经 RADV 可跑还是 RDNA4 新卡实测快于同卡 ROCm/HIP只要驱动提供 Vulkan 1.2 与 subgroup 算术扩展就能接入。配合COLI_VK_EXPERTS的驻留专家层、融合的注意力核与异步专家组它把“从磁盘流式拉专家”的瓶颈从 I/O 转移到了可并行的 GPU 计算上。动手前请务必确认三件事构建机有glslc、运行时设置COLI_NO_OMP_TUNE1、独立显卡开启 Resizable BAR。【免费下载链接】colibriRun frontier MoE models on hardware you already own — pure C, zero deps, experts streamed from disk. Tiny engine, immense model. 项目地址: https://gitcode.com/GitHub_Trending/colibri3/colibri创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考