news 2026/9/19 20:34:44

张量并行支持现状与多 GPU 拆分实践:从 ik_llama.cpp Issue 627 谈起

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
张量并行支持现状与多 GPU 拆分实践:从 ik_llama.cpp Issue 627 谈起

张量并行支持现状与多 GPU 拆分实践:从 ik_llama.cpp Issue #627 谈起

【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp

本文围绕 ik_llama.cpp 仓库中一则典型的 Feature Request(github-data/issues/627)展开,梳理社区对“张量并行(Tensor Parallelism)”的诉求背景、ik_llama.cpp 当前提供的多 GPU 拆分方案(--split-mode各模式)、对应命令行参数与源码实现依据,并结合 issue 讨论中用户的实测数据,帮助读者理解在 ik_llama.cpp 中如何配置多 GPU 推理、当前的性能边界与已知限制。

一、Issue #627 的诉求:为什么需要张量并行

2025 年 7 月 18 日,用户rankaiyx在 ik_llama.cpp 仓库提交了编号 627 的 Feature Request(当前状态为 Open),核心诉求是:在 ik_llama.cpp 中实现张量并行(Tensor Parallelism)支持

1.1 张量并行是什么

Issue 中对张量并行的定义是:一种用于大语言模型(LLM)推理的模型并行技术,将模型的张量计算(如矩阵乘法)分布到多个设备(GPU/TPU)上,使模型不同层的不同部分能够并行处理,从而提升推理速度与可扩展性。其关键特性包括:

  • 模型拆分(Model Splitting):将模型层(尤其是大型权重矩阵)拆分到多个设备;
  • 分布式计算(Distributed Computation):并行执行张量运算,减少计算时间;
  • 通信开销(Communication Overhead):需要设备间通信(如 AllReduce)来同步中间结果;
  • 高效扩展(Efficient Scaling):使超出单设备显存容量的大型模型也能完成推理。

典型使用场景是:模型尺寸超过单张 GPU 显存容量时的大规模 LLM 推理

1.2 动机:--split-mode row的性能差距

提交者给出的动机非常具体:当前通过--split-mode row实现的多 GPU 推理性能远低于 vLLM 或 mlc-llm。其引用的实测数据如下(注意:以下均为 issue 提交者报告的个人环境数据,非项目官方基准):

  • 平台:4×P100(Pascal 架构,较老的计算卡);
  • 模型:Qwen2.5-72B-4bit;
  • vLLM / mlc-llm:生成速度约20 tok/s
  • llama.cpp(--split-mode row):生成速度约10 tok/s,约为前者的一半。

此外,提交者还补充了两个背景因素:mlc-llm 开发活跃度较低、支持模型较少;而 vLLM 的 1.0 版本将放弃大量 Turing 及更老的硬件。因此他希望在 ik_llama.cpp 中通过张量并行获得更好的老硬件多卡性能。

需要明确的是,issue 编号 627 在仓库记录中仍为 Open 状态,即该项目当时并未完整落地独立的张量并行实现。下文所述的--split-mode各拆分模式,是该 issue 讨论时项目中实际存在的多 GPU 推理方案。

二、ik_llama.cpp 现有的多 GPU 拆分方案:split-mode 全景

虽然 issue 中提交者写的是--split-mode row,但当前仓库中-sm/--split-mode的合法取值已经演进为四个模式。在 include/llama.h 中定义了枚举:

enum llama_split_mode { LLAMA_SPLIT_MODE_NONE = 0, // single GPU LLAMA_SPLIT_MODE_LAYER = 1, // split layers and KV across GPUs LLAMA_SPLIT_MODE_ATTN = 2, // splits self-attention computations across GPUs LLAMA_SPLIT_MODE_GRAPH = 3, // splits computations across GPUs };

命令行解析位于 common/common.cpp,对应关系如下:

命令行取值枚举值语义
noneLLAMA_SPLIT_MODE_NONE仅使用单张 GPU
layer(默认)LLAMA_SPLIT_MODE_LAYER按层与 KV 缓存拆分到多张 GPU
attnLLAMA_SPLIT_MODE_ATTN将 self-attention 计算拆分到多张 GPU
graphLLAMA_SPLIT_MODE_GRAPH将模型张量与计算图拆分到多张 GPU

其中graph模式最接近 issue 中“张量并行”的诉求:它不再只是按层切分,而是把单个层的权重张量与计算图节点分布到多张 GPU 上执行,并配合 REDUCE 算子做跨设备归约。

2.1 从源码结构看各模式的实现差异

在 src/llama.cpp 的设备分配逻辑中,可以看到三种路径的分野:

  • LLAMA_SPLIT_MODE_LAYER:按default_layer_device[]把每个重复层整体分配到某一设备,使用llama_default_buffer_type_offload();输出层同理。这是最传统、通信开销最小的“层级流水”拆分。
  • LLAMA_SPLIT_MODE_GRAPH/LLAMA_SPLIT_MODE_ATTN:当model.splits.size() > 1时,会构造一个llama_default_buffer_type_split()split_buft,并让每个层持有{ split_buft, offload_buft }双 buffer 类型——即权重按“拆分 buffer”存放、随计算图在各 GPU 间调度执行。ATTN模式还会根据splits[]比例用std::upper_bound把每一层落在对应的 GPU 上(src/llama.cpp)。

这也解释了为什么仓库中大量架构实现会同时判断GRAPHATTN两种模式。例如 src/llama-load-tensors.cpp 中的use_split_ctx、src/graphs/build_deepseek2.cpp 中的tp_mode(张量并行模式)标志,均把GRAPH/ATTN视为“按张量拆分”的统一入口。

2.2 拆分模式下张量如何存放与归约

GRAPH模式下,模型的重复层张量会按设备数量复制/切分。可以从 src/llama-model.h 看到一条关键逻辑:

if (split_mode == LLAMA_SPLIT_MODE_GRAPH && !devices.empty()) n_tensors *= devices.size();

即拆分模式下张量数量会乘以设备数——这正是张量并行“每个设备持有权重的一个切片”的典型形态。而跨设备的结果同步,则对应 issue 中提到的 AllReduce 语义:项目以REDUCE 算子的形式在计算图中完成多设备归约,GGML_OP_ADD等节点在graph调度下跨设备执行并同步(src/llama.cpp 的注释明确提到“the GPU where the last REDUCE op is performed”)。

三、多 GPU 推理的命令行实战

结合 common/common.cpp 的帮助文本,实际使用多 GPU 时最常用的参数如下。

3.1 选择拆分模式:-sm, --split-mode

-split-mode SPLIT_MODE
  • none:只用一块 GPU;
  • graph:把模型张量与计算图拆分到多张 GPU(最接近张量并行);
  • layer(默认):按层与 KV 拆分;
  • 仓库帮助文本中未列出attn,但解析器支持该取值(common/common.cpp)。

注意:-sm仅在编译启用了 CUDA/SYCL/Vulkan 后端时生效;否则会打印警告 “llama.cpp was compiled without CUDA/SYCL/Vulkan. Setting the split mode has no effect.”(common/common.cpp)。

3.2 控制张量在各 GPU 的分配比例:-ts, --tensor-split

-ts, --tensor-split SPLIT

以逗号分隔的“每块 GPU 分担的模型比例”,例如3,1表示把约 3/4 权重给第一块 GPU、1/4 给第二块。解析代码位于 common/common.cpp:参数以,/分割,逐项写入params.tensor_split[],未指定的设备权重置 0;同时要求split_arg.size() < llama_max_devices()

3.3 指定主 GPU 与设备列表

-mg, --main-gpu i # split-mode=none 时模型所在 GPU;graph/row 场景下用于中间结果与 KV 的 GPU -dev, --device dev1,dev2 # 显式指定参与 offload 的设备,如 CUDA0,CUDA1,RPC[192.168.0.1:8080] --max-gpu i # split mode 'graph' 下同时使用的 GPU 数量上限

其中-dev支持RPC[ip:port]形式的远端设备,说明多卡场景还可以跨机器扩展(见 examples/rpc)。

3.4 拆分模式专项开关

-smgs, --split-mode-graph-scheduling # 强制使用 Split Mode Graph Scheduling -smf16, --split-mode-f16 # GPU 间数据交换使用 f16(默认) -smf32, --split-mode-f32 # GPU 间数据交换使用 f32

这三个开关在 common/common.cpp 中解析(-smf16/-smf32当前被注释,尚未激活),并写入上下文参数split_mode_graph_scheduling(common/common.cpp)。在 src/llama.cpp 中,当split_mode == LLAMA_SPLIT_MODE_GRAPH时(且无张量覆盖或用户强制-smgs),会调用:

ggml_backend_sched_set_split_mode_graph(ctx->sched, true, cparams.scheduler_async);

该 API 声明于 ggml/include/ggml-backend.h,async参数表明拆分模式图的调度支持异步执行。若用户同时设置了张量覆盖(tensor overrides)又强制-smgs,日志会明确警告可能因组合不受支持而导致推理错误。

3.5 典型多卡启动示例

结合以上参数,一个在 2 张 GPU 上以 graph 模式运行的典型命令形如:

./build/bin/llama-cli -m Qwen2.5-72B-4bit.gguf \ -ngl 99 \ -sm graph \ -ts 1,1 \ -mg 0

其中-ts 1,1表示两卡均分权重,-mg 0指定主 GPU。需要提醒的是,graph模式对架构支持有前置条件(详见下文),实际使用前应先在低负载模型上验证。

四、issue 讨论中的实测反馈与已知限制

issue 的对话部分保留了多位用户的实测观察,这些是理解该功能现状的一手素材(均为用户个人环境数据,非官方基准):

  • 项目维护者的定位:ikawrakow(项目作者)回复表示“支持旧硬件并非本项目强项,而这恰恰是 mainline llama.cpp 的强项之一”,并建议将该 issue 提交给 llama.cpp 主线项目——这界定了该项目在多 GPU 能力上的优先级定位。

  • split-mode row 的实际表现:用户 Ph0rk0z 在 Command-A 模型上的对比测试显示:

    • ik_llama.cpp 在 split-mode row 下生成约17 tok/s,与主线 prompt 处理速度相当,但输出出现不连贯文本(“looks like parts of the training data or random text”);关闭 split-mode 后输出连贯但速度降到约12 tok/s
    • 主线 llama.cpp 并行时约12 tok/s,关闭后约9 tok/s;且两边的prompt 处理速度在 row 模式下都约减半
  • 后续建议:用户 saood06 的结论是“这个仓库提供了最快的可用生成速度”,建议针对 row 模式的连贯性问题以及 PP 速度减半问题分别提交 issue 跟踪。

从这些反馈可以看出,多 GPU 拆分(尤其是 row 语义)在当时存在两类典型问题:输出质量退化(可能与跨设备归约的数值/同步路径有关)与prompt 处理吞吐下降。这也与第 2.2 节所述 REDUCE 跨设备同步的通信开销互相印证。

五、现状与展望

截至仓库记录的 issue 状态,编号 627 仍为Open,即张量并行作为一个“独立完整特性”尚未在本仓库中统一落地;但仓库已经在GRAPH/ATTN拆分模式上实现了大量与张量并行同构的机制:

  • 张量级切分与多副本存放(src/llama-model.h);
  • 拆分 buffer 类型split_buft与计算图调度(src/llama.cpp);
  • 跨设备 REDUCE 归约与异步 graph 调度(ggml/include/ggml-backend.h、src/llama.cpp);
  • 多架构的tp_mode判定(如 src/graphs/build_deepseek2.cpp、src/graphs/build_minimaxm2.cpp)。

对于希望用老硬件(如 4×P100)跑超大模型的用户,务实路径是:先以-sm layer获得稳定的多卡可用性,再尝试-sm graph+-ts配置观察吞吐与输出质量,并注意对照 issue 讨论中已知的“row 模式输出不连贯 / PP 减半”风险。需要跟进张量并行完整实现进展的读者,可直接关注该 issue 的状态变化及-sm相关参数在 common/common.cpp 中的演进。

【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 20:34:05

ORA-01000 游标超限?让 Codex 走 TaoToken 查未关的 ResultSet

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 20:33:54

通达信资金能量指标:三维耦合模型解析

简介&#xff1a;本资源是一份面向股票量化交易初学者与通达信公式编写爱好者的实战型指标源码解析文档&#xff0c;聚焦主升浪行情识别这一核心需求。文档完整公开了「资金能量指标」副图公式源码及逐行注释&#xff0c;涵盖双路移动平均构造&#xff08;QQ/WW&#xff09;、动…

作者头像 李华
网站建设 2026/9/19 20:32:10

URP半透明渲染深度排序优化:Shader与Renderer Feature实战

1. 半透明渲染的痛点与URP管线特性拆解做过Unity项目的人大概率都遇到过这种场景&#xff1a;一个玻璃杯、一片树叶、一团烟雾&#xff0c;或者角色身上半透明的披风&#xff0c;在镜头转动到某些角度时&#xff0c;突然出现奇怪的色块、闪烁的条纹&#xff0c;或者前后层叠关系…

作者头像 李华
网站建设 2026/9/19 20:31:43

FUI验证实战:从Prefab节点改名到构建门禁自动化诊断

FUI 验证实战&#xff1a;从 Prefab 节点改名到生成诊断与构建门禁见过太多次这种场景了&#xff1a;某个周二的下午&#xff0c;策划在走查界面时顺口提了一句"这个按钮名字太随意了&#xff0c;改成BagButton吧"&#xff0c;程序随手在编辑器里把 Prefab 的节点重命…

作者头像 李华