菜单

后端

相关源文件

此页面概述了 llama.cpp 中的后端系统,该系统支持在不同硬件设备上执行张量计算。后端负责在 CPU、CUDA、Metal、Vulkan 等各种硬件平台上进行张量内存分配和计算。有关特定后端优化技术的更多信息,请参阅 核心库架构

后端架构概览

llama.cpp 中的后端系统设计为一种模块化架构,支持多种硬件加速选项。该系统围绕每个后端实现的一个通用接口,从而能够跨不同硬件平台无缝执行 GGML 操作。

后端系统包含几个关键组件:

  1. Buffer Type (ggml_backend_buffer_type_t):定义特定硬件平台的内存缓冲区属性。
  2. Buffer (ggml_backend_buffer_t):表示设备上分配的内存。
  3. Backend (ggml_backend_t):为缓冲区中存储的张量提供计算能力。
  4. Device (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 后端支持各种指令集和优化。

  • AVX、AVX2、AVX512
  • FMA、F16C
  • Intel 处理器的 AMX 指令集
  • ARM Neon 优化
  • Loongson 处理器的 LASX 和 LSX
  • 使用 OpenMP 进行多线程

CPU 后端还可以编译成多个针对特定指令集的变体,从而允许运行时选择最优化的实现。

来源:ggml/src/ggml-cpu/CMakeLists.txt284-312 ggml/src/ggml-cpu/ggml-cpu.c211-376

GPU 后端

  • CUDA 后端:用于 NVIDIA GPU。
  • Metal 后端:用于 Apple GPU(Mac、iPhone、iPad)。
  • Vulkan 后端:跨平台 GPU 支持。
  • SYCL 后端:用于 Intel GPU。
  • HIP 后端:用于 AMD GPU。
  • OpenCL 后端:通用的跨平台 GPU 支持。
  • MUSA 后端:用于摩尔线程 GPU。
  • CANN 后端:用于华为昇腾 NPU。

来源: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

创建自定义后端

要实现新后端,开发者需要:

  1. 定义一个新的缓冲区类型,实现 ggml_backend_buffer_type_i
  2. 创建具有 ggml_backend_buffer_i 的缓冲区实现。
  3. 实现后端接口 ggml_backend_i
  4. 将后端注册到注册表中。

该系统使用插件架构(当使用 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_DLBUILD_SHARED_LIBS 来启用后端的动态加载。

来源: ggml/CMakeLists.txt144-206 ggml/src/CMakeLists.txt185-206

总结

llama.cpp 中的后端系统提供了一个灵活的架构,用于在各种硬件平台上执行张量运算。通过实现通用接口,该系统允许应用程序为可用的硬件(无论是 CPU、GPU 还是其他加速器)选择最合适的后端。

这种模块化方法使 llama.cpp 能够在一系列设备上高效运行大型语言模型,从具有多个 GPU 的高端服务器到具有专用硬件的移动设备。