llama.cpp b10814发布:OpenCL后端新增 9 种逐元素算子并大幅优化拷贝路径
新版llama.cpp将sgn、elu、trunc等 9 个逐元素一元算子从CPU回退改为OpenCL执行,并为连续张量拷贝与CONCAT扩展了类型支持。
AI解读:这次更新主要让OpenCL后端在更多常见模型结构上摆脱CPU回退。此前,sgn、elu、hardswish等 9 个逐元素算子、CONCAT操作以及大块连续拷贝都会回调CPU,而CPU与GPU之间的反复同步恰恰是移动端推理的常见瓶颈。本次修复直接切中这个点:一方面为这些算子补充GPU kernel(在Adreno 840/850上全部测试通过),另一方面把连续f32拷贝从每行 64 个work item提升为整个设备并行——针对mamba2、gated-delta-net等循环状态缓存(单行 524288 个浮点数)的逐层拷贝,改动非常对症。对普通用户而言,如果使用OpenCL后端跑mamba2或含gated-delta-net的模型,这次更新有望缩短等待;新算子的加入则让更多模型图可以完整在GPU上执行。另外,CONCAT操作支持的类型从仅f32扩展到f16/bf16/i8/i16/i32/i64等全部非量化类型,与新算子一样按字节宽度而非具体类型生成kernel,后续新增同宽度类型无需额外开发。目前这些改进已在Adreno 840/850/740等设备验证,但暂未看到其他GPU厂商的测试数据;需要OpenCL的用户可尝试升级,若遇到驱动兼容问题,仍可通过设置环境变量回退到原有拷贝路径。
llama.cpp于 2026 年 9 月 4 日发布b10814版本。本次更新将 9 个此前在OpenCL后端回退到CPU的逐元素一元算子(sgn、step、elu、hardswish、hardsigmoid、floor、ceil、round、trunc)改为在GPU上执行。
贡献者同时优化了连续f32张量的拷贝路径,使单行大缓冲(如mamba2、gated-delta-net的循环状态缓存,单行 524288 个浮点数)的拷贝不再局限于 64 个work item,而是按float4粒度在整个设备上并行。该优化默认启用,可通过环境变量GGML_OPENCL_CPY_FLAT=0 回退到旧路径。
CONCAT操作的支持类型也从仅f32扩展到所有非量化且块大小为 1 的类型,包括f16/bf16/i8/i16/i32/i64,kernel按字节宽度(b1/b2/b4/b8)生成,与CUDA后端的做法一致。
新增 9 种逐元素算子,覆盖非连续输入
新增的 9 个算子(sgn、step、elu、hardswish、hardsigmoid、floor、ceil、round、trunc)采用与原有ABS算子相同的变体设计:f32、f32_4(vec4)、f16、f16_4(vec4)以及面向非连续输入的stride寻址方式f32_nc/f16_nc。实现位于新增的kernels/unary_ext.cl(宏生成),并附带一个仿照ggml_cl_abs的共享分发辅助函数ggml_cl_unary_ext,以及supports_op和compute-forward相关用例。
数值在float中计算(f16变体读取/写入half并转换),因此条件算子(step、elu)与CPU参考实现一致;vec4形式使用select() 进行分支。测试在Adreno 840和 850(E17)上通过test-backend-ops验证,9 个算子的所有用例(包括vec4和非连续变体)均通过(8/8 或 14/14)。
连续f32拷贝改为全设备并行
原有kernel_cpy_f32_f32将每个workgroup映射到一行 (i01,i02,i03),并在该workgroup的lanes上跨越行,主机端启动ne01*MIN(64,ne00) 个work item。因此当张量行数少但行长度大时,整个拷贝只在一个workgroup上运行。对于mamba2和gated-delta-net的循环状态缓存(单行 524288 个浮点数,每层每图拷贝一次),实际只落到 64 个work item上。
新实现检测到两侧张量均连续且元素总数相同时,将拷贝视为线性移动,按每个work item处理一个float4的方式在整个设备上分发。该路径使用vload4/vstore4而非float4强制转换,因为缓冲区可能带有任意的 4 字节视图偏移,vload4/vstore4只需标量类型的对齐要求。kernel按需创建,若驱动拒绝则回退而不中止。
CPY、DUP和CONT操作在Adreno 840和 740 上启用或禁用新路径时均为 217/217 通过。设置GGML_OPENCL_CPY_FLAT=0 可强制使用旧kernel。
CONCAT支持所有非量化易拷贝类型
CONCAT此前仅支持f32。本次更新将其扩展到所有“easy-copy”类型——即块大小为 1、元素大小为 1、2、4 或 8 字节的非量化类型,包括f16/bf16/i8/i16/i32/i64以及f32。kernel按元素字节宽度(b1/b2/b4/b8)而非具体ggml类型生成,外加一个打包的b4快速路径,与CUDA后端对同一算子的做法一致。
supports_op同样基于该属性进行门控,因此新增的同宽度类型无需额外改动即可被支持。验证在Adreno 840 / A8X以及X2-90 / X2E上通过test-backend-ops。