Skip to content

GGML 张量库基础 — 概念

张量 (Tensor)

GGML 中的张量用 ggml_tensor 结构体表示:

c
struct ggml_tensor {
    enum ggml_type type;                  // 数据类型 (F32, F16, Q4_0, ...)
    struct ggml_backend_buffer * buffer;  // 所属后端缓冲区
    int64_t ne[GGML_MAX_DIMS];            // 每个维度的元素数
    size_t  nb[GGML_MAX_DIMS];            // 每个维度的字节步长
    enum ggml_op op;                      // 操作类型
    int32_t op_params[GGML_MAX_OP_PARAMS / sizeof(int32_t)]; // 操作参数
    int32_t flags;                        // 标志位
    struct ggml_tensor * src[GGML_MAX_SRC]; // 输入张量(图边)
    void * data;                          // 数据指针
    char name[GGML_MAX_NAME];             // 张量名
    // ... 其后还有 view_src / view_offs / extra / padding 等
};

注:n_dims 并非结构体成员,而是辅助函数 ggml_n_dims()(按 ne[] 推断实际维度数);旧版的 grad 字段早已移除,梯度现在通过计算图的 op / src[] 链路传递。

关键设计:

  • ne[] (number of elements) — 每维元素数,如 [rows, cols]
  • nb[] (number of bytes) — 每维字节步长,支持非连续内存
  • type — 支持 F32、F16、以及多种量化类型 (Q4_0, Q5_1, Q8_0 等)

数据类型

类型比特数说明
GGML_TYPE_F3232标准 float
GGML_TYPE_F1616半精度
GGML_TYPE_BF1616BF16(部分后端通过转换为 F16 支持,如 OpenCL)
GGML_TYPE_Q4_04.54-bit 量化 (block)
GGML_TYPE_Q5_16.05-bit 量化(含 min offset)
GGML_TYPE_Q8_08.58-bit 量化
GGML_TYPE_Q2_02.252-bit 量化(block QK2_0=64,18 字节:1×f16 scale + 16 字节 2-bit 打包值)
GGML_TYPE_IQ4_XS4.25超低比特量化

计算图

GGML 使用计算图描述运算:

构建方式:

c
struct ggml_context * ctx = ggml_init(params);
struct ggml_tensor * x = ggml_new_tensor_1d(ctx, GGML_TYPE_F32, 1);
ggml_set_param(ctx, x);
struct ggml_tensor * a = ggml_new_tensor_1d(ctx, GGML_TYPE_F32, 1);
struct ggml_tensor * b = ggml_new_tensor_1d(ctx, GGML_TYPE_F32, 1);
struct ggml_tensor * x2 = ggml_mul(ctx, x, x);
struct ggml_tensor * f = ggml_add(ctx, ggml_mul(ctx, a, x2), b);

自动微分

  • 标记为 param 的张量会自动计算梯度
  • ggml_set_param(ctx, tensor) 将张量标记为可训练参数
  • 反向传播通过 ggml_build_backward_expand() 自动构建梯度图

内存管理

  • ggml_context 是一个内存池,所有张量从中分配
  • ggml_init() 创建上下文,需指定内存大小
  • ggml_free() 一次性释放所有张量

性能优化

  • 量化查找表 (quant LUT) 的初始化现已并行化(多线程同时构建不同类型的 LUT),缩短启动时间
  • GGML 版本已升级至 0.23.0(从 0.13.1 起经 0.14.0 → … → 0.17.0 → 0.18.0/0.18.1 → 0.19.0 → 0.20.0-0.20.2 → 0.21.0 → 0.22.0 → 0.23.0 逐级提升,通过 sync: ggml 子树合并引入)

最近窗口(e9fa0781f → 9113cc188,b9840 → b11065,693 commits)GGML 0.17.0 → 0.23.0:六个小版本的跨版本升级,但 GGML_OP_COUNT(101)与 GGML_TYPE_COUNT(43)均未变化——本窗口的变化在语义层:ggml_prec 精度规范重写(见下)、ggml_clamp 拆分为非原地 + ggml_clamp_inplace、新增 ggml_rope_set_offset()(前 n_offs 维不旋转)、ggml_ssm_scan 增加第 9 参 K(循环态回滚快照)、新增 ggml_build_forward_order();RPC 协议 4.0.3 → 6.0.0。详见 推理图采样量化

ggml_prec 精度规范(重写)

enum ggml_prec 从「F32/DEFAULT 二选一」扩展为一组数值等级#26675):

c
GGML_PREC_UNDEFINED / GGML_PREC_DEFAULT = 0,
GGML_PREC_F32  = 10,   // 累加必须 F32
GGML_PREC_BF16 = 15,
GGML_PREC_F16  = 20,
GGML_PREC_Q8   = 30,   // 允许把 F32/BF16/F16 数据降精度到 Q8_0
GGML_PREC_Q4   = 40,   // 允许降到 Q4_K / NVFP4 / MXFP4 等 4-bit

配套两个通用 setter:ggml_prec_set_acc(t, prec)(累加精度,适用 MUL_MAT / MUL_MAT_ID / FLASH_ATTN_EXT)与 ggml_prec_set_src(t, prec, idx)(允许实现把 src[idx] 内部降精度,仅 MUL_MAT 系且 idx==1)。旧的 ggml_mul_mat_set_prec / ggml_flash_attn_ext_set_prec 已标记 deprecated。

COL2IM_1D 算子

GGML_OP_COL2IM_1Dggml_col2im_1d())是 IM2COL 系列的逆运算:

  • IM2COL / IM2COL_3D — 将图像/特征图展开成列矩阵,便于用矩阵乘实现卷积
  • COL2IM_1D — 把列矩阵反向聚合回 1D 特征图,用于卷积的反向梯度计算

算子在上游引入后,本窗口补齐了 CUDAVulkan 后端的实现(Metal 端的 1D im2col 路径此前已修复),使音频模型在各加速后端上都能走反向梯度。

该算子主要服务于音频模型(如 Whisper 的 1D 卷积层)在自动微分路径上的需求。

CPU 后端算子优化

x86 / ARM / Power 上的核心 kernel 也在持续打磨:

  • AMX 优化 — Intel AMX 路径进一步调优矩阵乘
  • Power10 / Power11 — power10 的 Q8/Q4 MMA matmul 支持 K-tail(处理非整除尾部),power11 后端按编译器支持条件启用
  • SVE 修复ggml_vec_dot_f32 中残留的 SVE 路径修正,避免在非目标平台误用

算子定义与后端实现是两件事:一个 GGML_OP_* 先在头文件声明并给出 CPU 参考,各硬件后端(CUDA/Vulkan/Metal/…)随后逐步补齐各自的 kernel。本窗口的 col2im_1d(CUDA/Vulkan)与 rope_back(Metal)就属此类"已有算子补后端"。

相关概念