hcomm:昇腾集群通信的底层原语

HCCL 管着 AllReduce、AllGather 这些高层集合通信操作。这些操作最终拆解成最基本的通信原语------Send、Recv、Broadcast。hcomm 就是负责这些底层通信原语的仓库。

HCCL 和 hcomm 的分工清晰:HCCL 负责通信算法(Ring AllReduce 怎么切分数据、树形 AllGather 怎么组织),hcomm 负责把这些算法翻译成硬件上的实际收发操作。


hcomm 与 HCCL 的关系

通信栈的分层:

复制代码
应用层:torch.distributed.all_reduce
  ↓
通信库层:HCCL------通信算法实现
  ↓
通信算子层:hcomm------底层 Send/Recv 原语
  ↓
硬件层:HCCS 互联 / RoCE 网络

HCCL 的 AllReduce 拆解为 ReduceScatter + AllGather。其中 ReduceScatter 内部调用 hcomm 的 SendRecv 原语来传输数据块。

cpp 复制代码
// HCCL 的 ReduceScatter 简化实现
// 内部调用 hcomm 原语
void ReduceScatter(float* send_buf, float* recv_buf, int count, int rank, int nranks) {
    // 切分数据
    int chunk_size = count / nranks;
    int recv_chunk = (rank - 1 + nranks) % nranks;
    int send_chunk = rank;
    
    for (int step = 0; step < nranks - 1; step++) {
        // hcomm 的发送和接收原语
        hcomm::Send(send_buf + send_chunk * chunk_size, chunk_size, next_rank);
        hcomm::Recv(temp_buf, chunk_size, prev_rank);
        
        // 在接收到的数据上做元素求和
        for (int i = 0; i < chunk_size; i++) {
            send_buf[send_chunk * chunk_size + i] += temp_buf[i];
        }
        
        send_chunk = (send_chunk - 1 + nranks) % nranks;
        recv_chunk = (recv_chunk - 1 + nranks) % nranks;
    }
}

HCCL 管"数据怎么切"和"每步传给谁",hcomm 管"怎么把数据发过去"和"怎么把数据接回来"。


Tensor 同步为什么会成为瓶颈

分布式训练中每步的通信量由模型大小决定。LLaMA-70B 的梯度 Tensor 约 140GB。Ring AllReduce 把 8 卡场景的每卡通信量降到约 35GB。

35GB 的传输在 HCCS(100GB/s)上需要约 350ms。训练一个 step 的前向+反向计算约 500ms。通信占了 40% 的时间。

hcomm 级别的 Send/Recv 延迟包括:

  1. DMA 准备。 hcomm 在发送前需要把数据从发送方的计算 Buffer 搬移到通信 Buffer------约 5-15μs
  2. 链路传输。 数据在 HCCS 链路上传输------跟数据量成正比
  3. DMA 完成。 接收方从通信 Buffer 搬回计算 Buffer------约 5-15μs

优化方向:hcomm 支持零拷贝路径------发送方直接读计算 Buffer 做 DMA 传输,不经过通信 Buffer。零拷贝适用于训练中的梯度同步(数据已经在显存中),省掉两次 Buffer 搬运。


昇腾通信链路解析

卡 0 向卡 1 发送数据的完整链路:

复制代码
卡 0:
  hcomm::Send(buffer, size, rank=1)
    → 通信 Buffer 分配
    → DMA 从计算 Buffer → 通信 Buffer(如果走非零拷贝)
    → HCCS 链路传输启动
    → Doorbell 通知卡 1

HCCS 链路:
  数据从卡 0 的显存 → PCIe/HCCS → 卡 1 的显存

卡 1:
  HCCS 控制器收到 Doorbell 信号
    → DMA 从通信 Buffer → 计算 Buffer
    → 通知 hcomm::Recv 调用者"数据已就绪"

整个过程约 10-15μs 的固定开销 + 数据量 / 带宽的可变开销。


分布式推理中的通信

推理场景的通信模式跟训练不同。训练是 AllReduce(每张卡发数据给所有卡),推理是 AllGather(每张卡从所有卡收集计算分片)。

以 8 卡张量并行推理 LLaMA-13B 为例:

复制代码
Attention 计算时每张卡持有 1/8 的 Head。
每张卡算完自己的 Attention 分片后,需要把所有分片拼起来得到完整的 Attention 输出。
  → AllGather 操作
  → 每张卡把本卡的分片广播给所有卡
  → 每张卡持有完整结果

AllGather 的通信量 = (n-1) × slice_size / n。Attention Head 分片大小 = B × n_heads × seq_len × head_dim / 8。Batch=1、n=4096 时单步约 4MB。8 卡 AllGather 的通信量约 28MB。

hcomm 在 AllGather 场景中支持 Ring 算法和 Tree 算法两种实现。Ring 适合小数据量(延迟低),Tree 适合大数据量(带宽高)。HCCL 根据数据量自动选择。

hcomm 的数据传输路径

hcomm 的 Send 操作涉及的数据路径:

  1. 发送方将数据从计算 Buffer 拷贝到通信 Buffer(如果是零拷贝模式则跳过)
  2. 通信 Buffer 的物理地址注册到 DMA 引擎
  3. DMA 引擎透过 HCCS 或 PCIe 将数据传输到接收方的通信 Buffer
  4. 接收方将数据从通信 Buffer 拷贝到计算 Buffer(零拷贝模式也跳过)

非零拷贝路径涉及 2 次显存拷贝,零拷贝路径 0 次。零拷贝的代价是需要额外的地址映射------通信双方需要预先注册显存段的访问权限。这个注册在通信域初始化时一次性完成。

hcomm 在推理场景中的使用

推理场景中的 hcomm 主要用于张量并行通信。LLaMA-13B 在 8 卡上做张量并行推理时,每步 Attention 计算需要跨卡 AllGather 结果。hcomm 的 AllGather 原语通过一条 hcomm::AllGather(send_buf, recv_buf, count, comm) 调用完成------内部自动拆解为 Ring 算法或 Tree 算法的 Send/Recv 序列。

参考仓库

hcomm 通信算子库

HCCL 集合通信库

相关推荐
狂奔蜗牛(bradley)8 小时前
深度学习三大基础激活函数详解:Sigmoid、Tanh、ReLU 公式、导数、图像与优缺点对比
人工智能·深度学习
AI服务老曹9 小时前
边云协同视频分析性能优化指南:多站点部署下的资源瓶颈突破与调优实战
性能优化·音视频
船厂电气自动化ai大模型9 小时前
AI大模型与数学 第32课 函数凹凸性与二阶导数:拐点求解、凹凸区间计算(10道二阶导数计算题)
数据结构·人工智能·python·深度学习·算法
小O的算法实验室11 小时前
IEEE TII,学习为多目标深度学习生成偏好
人工智能·深度学习·学习
江畔柳前堤11 小时前
Function Calling 与 Tool Calling:从认知到工程的全景深度解析
开发语言·网络·人工智能·深度学习·算法·机器学习·php
qq_4221525714 小时前
Token到底是什么?Tokenizer分词机制与中文token开销入门科普
人工智能·python·深度学习
AndrewHZ14 小时前
【LLM技术全景】RAG 从原理到实战——检索增强生成完整指南
人工智能·深度学习·算法·llm·检索增强·生成式模型·rag
夏文强14 小时前
AI 技术全景架构科普:从算法到应用的一整套技术栈
人工智能·深度学习·机器学习·大语言模型·技术架构
是上好佳佳佳呀16 小时前
【深度学习|DAY04】神经网络深度学习笔记(下):损失函数、优化器与正则化
笔记·深度学习·神经网络
阿图灵16 小时前
基于 GRU 的 Seq2Seq 中英机器翻译:从 Tatoeba 语料到 BLEU 0.195
深度学习·gru·nlp·机器翻译·seq2seq