Appearance
GGML 后端与硬件抽象 — 代码走读
ggml/src/ggml-backend.cpp — 后端注册表
后端通过注册表模式管理:
c
// 注册后端(注册的是后端注册对象,而非 backend 实例本身)
void ggml_backend_register(ggml_backend_reg_t reg);现代 API 通过**设备(device)**枚举来发现后端,而不是按类型直接取一个 backend:
c
// 枚举所有已注册的设备
size_t ggml_backend_dev_count(void);
ggml_backend_dev_t ggml_backend_dev_get(size_t index); // 按下标取设备
ggml_backend_dev_t ggml_backend_dev_by_name(const char * name); // 按名称取设备
ggml_backend_dev_t ggml_backend_dev_by_type(enum ggml_backend_dev_type type); // 按类型取设备
// 再用设备初始化一个真正的后端实例
ggml_backend_t ggml_backend_dev_init(ggml_backend_dev_t device, const char * params);注意:
ggml_backend_register的参数类型是ggml_backend_reg_t(后端注册对象),而设备枚举走ggml_backend_dev_*系列函数。上述签名均见ggml/include/ggml-backend.h。
核心结构(定义于内部头 ggml/src/ggml-backend-impl.h,不在 公开头中):
c
struct ggml_backend {
ggml_guid_t guid; // 后端 GUID
struct ggml_backend_i iface; // 函数指针表
ggml_backend_dev_t device; // 所属设备
void * context; // 后端私有数据
};ggml_backend_i 是后端的主函数指针表(涵盖同步的图计算 graph_compute 等,以及可选的异步张量 / 事件操作),成员(节选,见 ggml-backend-impl.h):
c
struct ggml_backend_i {
const char * (*get_name)(ggml_backend_t backend);
void (*free)(ggml_backend_t backend);
// (可选)异步张量数据访问
void (*set_tensor_async)(ggml_backend_t backend, struct ggml_tensor * tensor, const void * data, size_t offset, size_t size);
void (*get_tensor_async)(ggml_backend_t backend, const struct ggml_tensor * tensor, void * data, size_t offset, size_t size);
bool (*cpy_tensor_async)(ggml_backend_t backend_src, ggml_backend_t backend_dst, const struct ggml_tensor * src, struct ggml_tensor * dst);
// (可选)完成所有挂起操作(支持异步时必需)
void (*synchronize)(ggml_backend_t backend);
// (可选)计算图计划(当前未使用)
ggml_backend_graph_plan_t (*graph_plan_create)(ggml_backend_t backend, const struct ggml_cgraph * cgraph);
void (*graph_plan_free)(ggml_backend_t backend, ggml_backend_graph_plan_t plan);
void (*graph_plan_update)(ggml_backend_t backend, ggml_backend_graph_plan_t plan, const struct ggml_cgraph * cgraph);
enum ggml_status (*graph_plan_compute)(ggml_backend_t backend, ggml_backend_graph_plan_t plan);
// 计算图(后端支持异步时永远异步)
enum ggml_status (*graph_compute)(ggml_backend_t backend, struct ggml_cgraph * cgraph);
// (可选)事件同步
void (*event_record)(ggml_backend_t backend, ggml_backend_event_t event);
void (*event_wait) (ggml_backend_t backend, ggml_backend_event_t event);
// (可选)对图中节点排序/优化(本窗口签名新增第三参 params,可回调 add_alloc_dep)
void (*graph_optimize)(ggml_backend_t backend, struct ggml_cgraph * cgraph, const struct ggml_backend_graph_optimize_params * params);
};旧笔记里列的
alloc_buffer、supports_op、get_buffer_alignment并不属于ggml_backend_i:缓冲区分配接口在ggml_backend_buffer_type_i,算子能力查询(supports_op)在设备接口ggml_backend_device_i,而get_buffer_alignment在当前源码中并不存在。
ggml/src/ggml-cpu/ — CPU 后端
关键文件:
ggml-cpu.c— CPU 后端主实现ggml-cpu.cpp— C++ 封装quants.c— 量化操作实现(位于ggml/src/ggml-cpu/)- ARM/NEON 优化代码位于
ggml/src/ggml-cpu/arch/arm/(如quants.c、repack.cpp、cpu-feats.cpp),不再有单独的ggml-cpu-aarch64.cpp文件
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
// 标量回退
#endifggml/src/ggml-cuda/ — CUDA 后端
关键文件:
ggml-cuda.cu— CUDA 后端入口(注意是.cu源文件,不是.cpp)mmq.cuh— 量化矩阵乘法 kernelfattn.cuh— Flash Attention kerneldequantize.cuh— 反量化 kernelfwht.cu/fwht.cuh— 快速 Walsh-Hadamard 变换
ggml/src/ggml-metal/ — Metal 后端
关键文件:
ggml-metal.cpp— Metal 后端主实现(C++)ggml-metal-context.m— Metal 上下文(Objective-C,与 MTLDevice/MTLCommandQueue 交互)ggml-metal-device.m/ggml-metal-device.cpp— 设备接口实现ggml-metal-common.cpp— 公共辅助代码kernels/*.metal(约 23 个文件)— Metal Compute Shaders,按算子拆分(+common.h/dequantize.h/quantize.h)
旧版单体
ggml-metal.m已不存在,后端被拆分成了上面的.cpp/.m多文件结构;随后单体ggml-metal.metal也被拆进kernels/目录(本窗口,b615f5b4b),metallib 相应拆成 8 个库并行编译加载——目录里已没有顶层.metal文件。另有ggml-metal-tuning.cpp/.h管理各 kernel 的调优参数。
Metal 后端利用 Apple Silicon 的统一内存:
objc
// Metal buffer 直接映射到 CPU 地址空间
id<MTLBuffer> metal_buffer = [device newBufferWithBytesNoCopy:ptr
length:size options:0 deallocator:nil];关键函数索引
| 函数 | 文件 | 说明 |
|---|---|---|
ggml_backend_cpu_init | ggml-cpu.cpp | 初始化 CPU 后端 |
ggml_backend_cuda_init | ggml-cuda.cu | 初始化 CUDA 后端 |
ggml_backend_metal_init | ggml-metal.cpp | 初始化 Metal 后端 |
ggml_backend_alloc_ctx_tensors | ggml-backend.cpp | 为张量分配设备内存 |
ggml_backend_graph_compute | 各后端 | 在设备上执行计算图 |