ggml 简介
ggml 是一个用 C 和 C++ 编写的底层机器学习(ML)库,专门用于 Transformer 推理。它是包括 llama.cpp、whisper.cpp、ollama、Jan、LM Studio 和 GPT4All 在内的流行设备端 LLM 项目的底层引擎。
ggml 的核心优势
ggml 旨在实现极简和高效,因而非常适合在资源受限的硬件上部署。其主要优势包括:
- 最小占用:核心库仅包含不到五个文件,编译后的二进制大小低于 1 MB。
- 简化编译:只需 GCC 或 Clang 即可进行基本编译,无需 GPU 支持,避免了复杂的构建工具。
- 广泛的硬件兼容性:支持 x86_64、ARM、Apple Silicon、CUDA 等硬件架构。
- 内存效率:库尽量减少张量存储和计算的开销,并支持量化张量以降低内存使用并可能提升性能。
技术权衡
作为一个仍在积极开发的底层库,ggml 存在以下局限性:
- 后端差异:并非所有张量操作在所有后端都受支持(例如,某个操作在 CPU 上可用,但在 CUDA 上不可用)。
- 开发复杂度:使用 ggml 需要深入的底层编程知识。
- 稳定性:由于仍在积极开发中,预期会有破坏性更改。
关键术语与概念
理解 ggml 需要熟悉若干提供细粒度性能控制的底层抽象:
ggml_context:用于存放张量、计算图以及可选数据的容器。ggml_cgraph:表示后端将执行的操作顺序的计算图。ggml_backend:执行计算图的接口,已有 CPU(默认)、CUDA、Metal、Vulkan 和 RPC 等实现。ggml_backend_buffer_type:与特定后端关联的内存分配器(例如,分配 GPU 内存)。ggml_backend_buffer:由buffer_type分配的缓冲区,可容纳多个张量的数据。ggml_gallocr:用于在计算图中高效管理张量的图内存分配器。ggml_backend_sched:调度器,可在多个后端之间分配计算(例如在 CPU 与 GPU 之间分割工作),并自动将不支持的操作分配到 CPU。
实现工作流
基本计算
对于诸如矩阵乘法等简单操作,ggml 的工作流包括:
- 为张量数据分配一个
ggml_context。 - 创建张量并分配数据。
- 为该操作(例如
ggml_mul_mat)定义一个ggml_cgraph。 - 通过
ggml_graph_compute_with_ctx执行计算。 - 获取结果并释放内存。
基于后端的计算
在使用特定硬件后端(如 CUDA)时,为确保高效的设备内存管理,流程更为细致:
- 初始化
ggml_backend。 - 仅为张量元数据分配一个
ggml_context。 - 创建张量元数据(形状和类型)。
- 分配一个
ggml_backend_buffer将张量存储在设备上。 - 将张量数据从 RAM 复制到后端缓冲区。
- 创建
ggml_cgraph和ggml_gallocr用于图的分配。 - 通过
ggml_backend_graph_compute执行计算。 - 将结果张量从设备缓冲区复制回 RAM。
调试计算图
开发者可以检查 ggml_cgraph 以验证操作顺序。库提供 ggml_graph_print 将图输出到控制台,ggml_graph_dump_dot 可将图导出为 Graphviz dot 格式以进行可视化渲染。
Sources
- OriginalIntroduction to ggml