Skip to content

GGML 后端与硬件抽象 — 代码走读

ggml/src/ggml-backend.cpp — 后端注册表

后端通过注册表模式管理:

c
// 注册后端
void ggml_backend_register(ggml_backend_t backend);

// 按类型查找后端
ggml_backend_t ggml_backend_get_by_type(enum ggml_backend_type type);

核心结构:

c
struct ggml_backend {
    struct ggml_backend_i iface;  // 函数指针表
    void * context;               // 后端私有数据
};

ggml_backend_i 定义了所有接口方法:

c
struct ggml_backend_i {
    const char * (*get_name)(ggml_backend_t backend);
    void (*free)(ggml_backend_t backend);
    ggml_backend_buffer_t (*alloc_buffer)(ggml_backend_t backend, size_t size);
    size_t (*get_buffer_alignment)(ggml_backend_t backend);
    bool (*supports_op)(ggml_backend_t backend, const struct ggml_tensor * op);
    ggml_status (*graph_compute)(ggml_backend_t backend, struct ggml_cgraph * graph);
    // ...
};

ggml/src/ggml-cpu/ — CPU 后端

关键文件:

  • ggml-cpu.c — CPU 后端主实现
  • ggml-cpu.cpp — C++ 封装
  • ggml-cpu-aarch64.cpp — ARM NEON 优化
  • ggml-cpu-quants.c — 量化操作实现

SIMD Kernel 选择

运行时检测 CPU 特性并选择最优 kernel:

c
#if defined(__AVX512F__)
    // AVX-512 实现 (512-bit SIMD)
#elif defined(__AVX2__)
    // AVX2 实现 (256-bit SIMD)
#elif defined(__ARM_NEON)
    // NEON 实现 (128-bit SIMD)
#else
    // 标量回退
#endif

ggml/src/ggml-cuda/ — CUDA 后端

关键文件:

  • ggml-cuda.cpp — CUDA 后端入口
  • mmq.cuh — 量化矩阵乘法 kernel
  • fattn.cuh — Flash Attention kernel
  • dequantize.cuh — 反量化 kernel

ggml/src/ggml-metal/ — Metal 后端

关键文件:

  • ggml-metal.m — Objective-C 后端实现
  • ggml-metal.metal — Metal Compute Shaders

Metal 后端利用 Apple Silicon 的统一内存:

objc
// Metal buffer 直接映射到 CPU 地址空间
id<MTLBuffer> metal_buffer = [device newBufferWithBytesNoCopy:ptr
    length:size options:0 deallocator:nil];

关键函数索引

函数文件说明
ggml_backend_cpu_initggml-cpu.cpp初始化 CPU 后端
ggml_backend_cuda_initggml-cuda.cpp初始化 CUDA 后端
ggml_backend_metal_initggml-metal.m初始化 Metal 后端
ggml_backend_alloc_ctx_tensorsggml-backend.cpp为张量分配设备内存
ggml_backend_graph_compute各后端在设备上执行计算图