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 集合通信库

相关推荐
有为少年3 小时前
Welford算法 | 从单一到批次
大数据·人工智能·深度学习·神经网络·算法·机器学习
钓了猫的鱼儿3 小时前
基于深度学习+AI的水下目标目标检测与预警系统(Python源码+数据集+UI可视化
人工智能·深度学习·智能手机
Hanniel4 小时前
Python __slots__ 入门指南
开发语言·python·性能优化
山屿落星辰6 小时前
ops-nn - 神经网络算子性能秘籍
人工智能·深度学习·神经网络
LaughingZhu6 小时前
Product Hunt 每日热榜 | 2026-05-22
人工智能·经验分享·深度学习·神经网络·产品运营
钓了猫的鱼儿7 小时前
基于深度学习+AI的玩手机行为目标检测与预警系统(Python源码+数据集+UI可视化界面+YOLOv11训练结果)
人工智能·深度学习·智能手机
解局易否结局7 小时前
从零上手 ops-transformer:一个有清晰路径感的学习计划
深度学习·学习·transformer
z小猫不吃鱼8 小时前
15 BEiT 论文精读:BERT Pre-Training of Image Transformers
人工智能·深度学习·bert
茗创科技8 小时前
脑室周围扩散率(PVeD)专题:一种评估类淋巴系统功能的DTI新方法(附高分文献下载)
深度学习·机器学习·matlab·脑网络