跳转至

2026

Data-as-Flag Communication

导言

我最初从外部技术资料了解到 Data-as-Flag 时,直觉上把它理解为三种省掉独立完成通知的方法:把 flag 塞进数据块、用数据校验值确认整批到达,或者先用特殊值填满接收区,再观察它是否被真实数据覆盖。

顺着这三个方向检查 NVIDIA 的公开资料后,答案很明确:NVIDIA 不但有相同思路,NCCL 的 LL/LL128 已经长期使用内嵌 flag;NCCL 2.31.2 的 LLA2A 又把它做成了面向低时延 All-to-All 的 payload + epoch 原子槽位。不过,公开实现更偏好显式 epoch,而不是让任意 payload 或 checksum 单独承担正确性。

CANN SHMEM Primitives

导言

我是零基础的算子开发初学者。第一次面对混合了 C++、Ascend C、SIMT 和 SHMEM 的通信算子,难点并不只是某个 API 不认识,而是同一行里往往同时出现模板参数、地址空间、数据搬运和同步语义。我想迁移这样的文件,就需要先回答四个问题:数据在哪里、谁在执行、这一句改变什么、下一步何时能使用结果

这篇文章从实际遇到的代码片段出发,把接口拆成尽量小的学习单元,再逐项解释模板参数、普通参数、返回值、地址偏移和同步范围。内容核对了 CANN 官方文档及 CANN/asc-devkitCANN/shmem 公开源码。尚未取得原算子完整文件,因此不虚构原文件行号,也不把业务封装的推测写成 API 定义。 文中的示意代码用于理解语义,未在 NPU 上编译运行。

Ascend DeepEP V2 Elastic Dispatch

导言

理解 elastic dispatch,需要把 Python 接口、native 调用链、对称内存申请和 device kernel 放在同一条执行路径中阅读。本页基于源页面收录的 cf9f87a51854ac20d608f683979171cb1fc65c69 版本证据,通过交互式 DAG、函数下钻和源码定位建立这些层次之间的对应关系。

核心边界是:host 路径与容量预算不代表 device 数据搬运已经实现。页面保留占位 kernel、缺失的数据布局与同步风险提示,帮助读者辨认已有实现和待补齐部分。

AIV UDMA Direct Drive

导言

刚理解 WQE 时,我看到一份 MoE dispatch 头文件没有调用 aclshmemx_udma_put_nbi(),也没有在发送热路径调用 aclshmemx_udma_quiet()。第一反应是:它是不是用 SIMT 加速了 WQE 下发,又用 Data-as-Flag 代替了完成通知?本文先沿标准接口追踪 Tensor 如何被降成地址、长度与 WQE,再把它与头文件中的批量直驱实现逐项比较。最后得到的边界是:SIMT 加速的是提交,Data-as-Flag 加速的是接收端就绪判断;二者都没有让 UDMA、SQ/CQ 生命周期或源 buffer 完成语义消失。

SHMEM UDMA Programming

导言

原生 URMA 要显式管理 Context、Segment、Jetty、WR 和完成队列。cann/shmem 提供了更高层的 PGAS 编程模型:程序主要面对“对称地址、目标 PE、put/get 和同步”。本文先解释 aclshmem_my_pe()aclshmem_n_pes()aclshmemx_udma_put_nbi(),再用两 PE 的 put-with-signal Case 说明数据和通知如何配合。

URMA Completion and Concurrency

导言

“WQE 和 Jetty SQ 还不能同时写?”这句话实际上混合了四个问题:软件和硬件能否同时访问队列、一个 SQ 能否挂多条请求、多个 Host 线程能否共享 Jetty、多个 AIV 能否直接驱动同一 QP。答案并不相同。本文先讲清提交与完成,再逐一划定并发边界。

URMA Write and Read

导言

本文把 URMA 官方样例中的核心 WRITE 路径收缩成一个教学 Case。目标不是复制几百行初始化代码,而是让零基础读者看懂:程序要准备哪些资源、每个结构体字段是什么意思、一条请求如何提交和确认完成。文中的核心代码按官方接口整理;初始化和带外交换用伪代码表示,实际编译时应以所使用 UMDK 版本的头文件与官方样例为准。

URMA Mental Model

导言

我刚开始接触 URMA 时,最容易卡住的问题不是某个函数不会调用,而是概念没有连成一条线:WQE 和 Jetty SQ 是什么关系,Segment 为什么要注册和导入,urma_post_jetty_send_wr() 提交之后又去了哪里。本文只做一件事:沿着一条 WRITE 请求的生命周期,把这些名词放回它们各自的位置。

Ascend DeepEP Dispatch Code Walkthrough

导言

阅读 4357 行 deepep_moe_dis_dispatch.h 时,最大的困难不是找到某个函数,而是持续维护 E2E 阶段、函数调用和具体源码行之间的对应关系。静态长文适合建立概念框架,却不便于在多条并行执行路径之间反复定位。

本页将同一份 Ascend C 参考实现组织为三轨联动工作区:左侧展示 Full-Mesh dispatch 的端到端执行 DAG,中间拆解当前函数的调用和分段逻辑,右侧保留完整源码。读者可以从阶段进入函数、从调用跳转到被调函数,也可以通过搜索和行号反向追踪同步协议与数据流。

Ascend DeepEP Ref Dispatch SIMT

导言

MoE dispatch 的困难并不只是把 token 从一张卡搬到另一张卡,而是要在 Top-K 路由运行时才确定的前提下,同时解决槽位分配、跨核协作、远程写入、完成通知和接收端连续排布。如果只盯着某个拷贝循环,很容易忽略控制面和同步协议才是这份实现的骨架。

本文以 deepep_moe_dis_dispatch.h 的 4357 行 Ascend C 参考实现为对象,从 SIMT 线程模型和 Full-Mesh 通信窗讲起,沿“本地打包 → 生成并提交 URMA WQE → doorbell 触发 → flag/count 对账 → 前缀和定位 → 输出重排”还原完整执行路径。页面把关键函数、内存布局、时序约束和可验证的优化方向放到一张连续地图中,帮助初学者建立从源码行号到通信机制的对应关系。