此页面概述了 llama.cpp 中的后端系统,该系统支持在不同硬件设备上执行张量计算。后端负责在 CPU、CUDA、Metal、Vulkan 等各种硬件平台上进行张量内存分配和计算。有关特定后端优化技术的更多信息,请参阅 核心库架构。
llama.cpp 中的后端系统设计为一种模块化架构,支持多种硬件加速选项。该系统围绕每个后端实现的一个通用接口,从而能够跨不同硬件平台无缝执行 GGML 操作。
后端系统包含几个关键组件:
ggml_backend_buffer_type_t):定义特定硬件平台的内存缓冲区属性。ggml_backend_buffer_t):表示设备上分配的内存。ggml_backend_t):为缓冲区中存储的张量提供计算能力。ggml_backend_dev_t):表示托管一个或多个后端的物理硬件设备。来源:ggml/include/ggml-backend.h24-30 ggml/src/ggml-backend-impl.h17-35
后端系统使用清晰的接口来定义每个组件应如何表现。
来源:ggml/src/ggml-backend-impl.h17-73
缓冲区类型定义了特定类型设备的内存分配和管理方式。
ggml_backend_buft_name:获取缓冲区类型的名称。ggml_backend_buft_alloc_buffer:分配特定类型的缓冲区。ggml_backend_buft_get_alignment:获取所需的内存对齐。ggml_backend_buft_get_max_size:获取最大分配大小。ggml_backend_buft_get_alloc_size:获取分配张量所需的字节数。ggml_backend_buft_is_host:检查缓冲区是否在主机内存中。ggml_backend_buffer_free:释放缓冲区。ggml_backend_buffer_get_base:获取缓冲区的基址。ggml_backend_buffer_init_tensor:在缓冲区中初始化张量。ggml_backend_buffer_set_tensor/get_tensor:在主机和设备之间传输数据。ggml_backend_buffer_clear:清除缓冲区内容。ggml_backend_buffer_reset:重置缓冲区状态。缓冲区可以具有不同的使用模式,由 enum ggml_backend_buffer_usage 定义。
GGML_BACKEND_BUFFER_USAGE_ANY:通用用途。GGML_BACKEND_BUFFER_USAGE_WEIGHTS:用于模型权重(针对只读进行了优化)。GGML_BACKEND_BUFFER_USAGE_COMPUTE:用于计算(临时存储)。来源:ggml/include/ggml-backend.h49-53 ggml/src/ggml-backend.cpp34-192
后端接口提供了张量计算的操作。
ggml_backend_name:获取后端的名称。ggml_backend_free:释放后端。ggml_backend_set_tensor_async/get_tensor_async:异步传输数据。ggml_backend_graph_compute:在后端计算图。ggml_backend_graph_plan_create/compute/free:规划和执行图计算。来源:ggml/src/ggml-backend.cpp196-380
llama.cpp 项目包含针对不同硬件平台的几种后端实现。
CPU 后端支持各种指令集和优化。
CPU 后端还可以编译成多个针对特定指令集的变体,从而允许运行时选择最优化的实现。
来源:ggml/src/ggml-cpu/CMakeLists.txt284-312 ggml/src/ggml-cpu/ggml-cpu.c211-376
来源:ggml/src/CMakeLists.txt302-312 ggml/include/ggml-metal.h ggml/include/ggml-cann.h
后端需要注册到后端注册表中才能使用。
应用程序可以根据设备类型、可用内存或特定功能来选择后端。
来源:ggml/src/ggml-backend.cpp729-897
分配过程包括从缓冲区类型创建缓冲区,然后在该缓冲区内初始化张量。应用程序为了效率,会在共享缓冲区中管理多个张量。
后端系统包含一个分配器接口,用于更高级的内存管理模式。
ggml_tallocr:用于顺序分配的尾部分配器。ggml_gallocr:用于分配计算图所需的张量的图分配器。来源:ggml/src/ggml-alloc.c76-170
使用后端的典型工作流程包括:
此过程允许在目标硬件上高效执行复杂的神经网络操作。
来源:ggml/src/ggml-cpu/ggml-cpu.cpp110-175
系统支持将计算分布到多个后端。
ggml_backend_tensor_get_device:确定张量在哪个设备上分配。ggml_backend_graph_split:将计算图拆分到多个后端。ggml_backend_multi_backend_execute:使用多个后端执行图。后端支持异步操作。
ggml_backend_tensor_set_async/get_async:非阻塞数据传输。ggml_backend_event:同步原语。ggml_backend_synchronize:等待所有操作完成。来源:ggml/src/ggml-backend.cpp234-260
要实现新后端,开发者需要:
ggml_backend_buffer_type_i。ggml_backend_buffer_i 的缓冲区实现。ggml_backend_i。该系统使用插件架构(当使用 GGML_BACKEND_DL 构建时),允许将后端作为动态库加载。
来源:ggml/src/CMakeLists.txt220-251
后端系统在构建时通过各种 CMake 选项进行配置。
GGML_CPU:启用 CPU 后端(默认启用)。GGML_CUDA:为 NVIDIA GPU 启用 CUDA 后端。GGML_METAL:为 Apple GPU 启用 Metal 后端。GGML_VULKAN:启用 Vulkan 后端。GGML_SYCL:为 Intel GPU 启用 SYCL 后端。GGML_HIP:为 AMD GPU 启用 HIP 后端。GGML_OPENCL:启用 OpenCL 后端GGML_MUSA:启用 MUSA 后端可以使用 GGML_BACKEND_DL 和 BUILD_SHARED_LIBS 来启用后端的动态加载。
来源: ggml/CMakeLists.txt144-206 ggml/src/CMakeLists.txt185-206
llama.cpp 中的后端系统提供了一个灵活的架构,用于在各种硬件平台上执行张量运算。通过实现通用接口,该系统允许应用程序为可用的硬件(无论是 CPU、GPU 还是其他加速器)选择最合适的后端。
这种模块化方法使 llama.cpp 能够在一系列设备上高效运行大型语言模型,从具有多个 GPU 的高端服务器到具有专用硬件的移动设备。