news 2026/9/20 13:40:15

PyPTO SIMT atomic_cas 原子比较交换 API 详解:从接口语义到 Ascend 950 端到端实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PyPTO SIMT atomic_cas 原子比较交换 API 详解:从接口语义到 Ascend 950 端到端实现
  • 人工智能
  • 编译器
  • 模型编译
  • 高性能计算
  • 深度学习
  • CANN

【免费下载链接】pypto

PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。

项目地址:https://gitcode.com/cann/pypto
点击查看免费下载

PyPTO(Parallel Tensor/Tile Operation 编程范式)在pypto_pro.language.simt命名空间下提供了完整的 SIMT 原子操作族(atomic_addatomic_exchatomic_casatomic_inc等)。其中atomic_cas(Compare-And-Swap,比较并交换)是最基础也最通用的同步原语:它以原子方式比较目标元素与期望值,相等时写入新值,并返回比较前的旧值,是自旋锁、单次初始化、唯一 Winner 选举等并发算法的核心构件。本文基于 atomic_cas API 文档,结合仓库内 IR 构建、CCE 后端代码生成与端到端测试源码,完整讲解该接口的调用约束、数据类型规则、返回值语义,并给出可直接运行的 Kernel 示例与源码级实现路径。

功能语义:一次不可分割的"读-比较-写"

atomic_cas对目的操作数target执行如下不可分割(原子)的步骤序列:

  1. 读取target的旧值;
  2. 将旧值与compare(期望值)比较;
  3. 若二者相等,将value写入target;否则target保持不变;
  4. 返回比较发生前的target旧值。

整个过程对 SIMT 线程网格中的其他线程完全不可见中间状态,因此并发线程同时调用atomic_cas时,只会有一个线程在某个时刻"赢得"写入权,其余线程要么看到旧值已被改写而放弃,要么在后续轮次中重新尝试。仓库中的 API 声明(python/pypto_pro/language/_simt_api.py)将其概括为:"Atomically compare and exchange one Tile or Tensor element, returning its old value."

函数原型

pypto_pro.language.simt.atomic_cas( target: Scalar, compare: Scalar, value: Scalar, ) -> Scalar

参数说明

参数输入/输出说明
target输入目的操作数,Scalar 类型。必须直接传入 Tile 或 Tensor 的单元素下标访问表达式,例如ub_tile[0, 0]gm_tensor[0, 0]
- UB Tile:必须位于 UB,使用 ND 格式,支持 DT_INT32、DT_UINT32、DT_FP32。
- GM Tensor:必须为 ND 格式,支持 DT_INT32、DT_UINT32、DT_FP32、DT_INT64、DT_UINT64。
compare输入源操作数,Scalar 类型,表示期望值。数据类型必须与 target 一致;数值字面量按 target 的数据类型处理,整数目的操作数不接受浮点字面量。
value输入源操作数,Scalar 类型,表示比较相等时写入的新值。数据类型必须与 target 一致;数值字面量按 target 的数据类型处理,整数目的操作数不接受浮点字面量。

两点关键细节需要特别强调:

  • target 必须"直接"写成下标访问表达式atomic_cas的底层实现需要同时拿到"容器引用(Tile/Tensor)"和"元素偏移量"两个信息,因此不能先取出元素再传入,例如tmp = tile[0, 0]; atomic_cas(tmp, ...)这类间接写法是不符合接口约定的。这一约束在 IR 层有明确体现:atomic_cas构建函数接收的是container(容器)与offset(偏移)两个独立参数(见下文源码分析)。
  • 字面量按 target 数据类型解释compare/value传数值字面量时不需要显式 cast,框架按target的数据类型解释该字面量;但对于整数类型的目标元素,传入浮点字面量(如0.0)是不被接受的,应保持类型一致。

数据类型与产品支持矩阵

atomic_cas对不同存储位置的数据类型支持并不完全相同,使用前请对照下表:

存储位置格式要求支持的数据类型
UB Tile必须位于 UB、ND 格式DT_INT32、DT_UINT32、DT_FP32
GM Tensor必须为 ND 格式DT_INT32、DT_UINT32、DT_FP32、DT_INT64、DT_UINT64

产品支持情况(以当前仓库文档为准):

  • Ascend 950PR / Ascend 950DT:支持
  • Atlas A3 训练系列产品 / Atlas A3 推理系列产品:不支持
  • Atlas A2 训练系列产品 / Atlas A2 推理系列产品:不支持

仓库端到端测试(python/tests/st/pypto_pro/frontend/simt/atomic/test_atomic_cas.py)在启动前会检查设备名是否包含Ascend950_require_a5函数),不满足则跳过测试,与文档声明的产品支持范围一致。

调用约束:SIMT 上下文

atomic_cas只能在由@pypto_pro.language.vector_function(mode="simt")定义的SIMT 入口函数SIMT 辅助函数中调用,不能在标量/向量上下文或其他编程范式下直接使用。这是因为该操作是 SIMT 线程级并发语义的一部分:只有在一个由多线程并行执行的 SIMT 函数中,"多个线程竞争同一元素"的场景才有意义。

一个典型的 SIMT Kernel 需要两层结构:

  • 外层@pl.jit()函数负责声明 Tensor 参数、创建 UB Tile(如需)、编排pl.section_vector()等流水区域,并以simt_func线程数的语法启动 SIMT 函数;
  • 内层@pl.vector_function(mode="simt", max_threads=...)函数内部编写逐线程执行的代码,atomic_cas就写在这里。

返回值说明

atomic_cas返回比较发生前target值,返回值类型与target一致。因此可以通过返回值判断本次交换是否成功:

  • 返回值== compare:说明比较时旧值恰好等于期望值,本次写入成功,该线程"赢得"竞争;
  • 返回值!= compare:说明旧值已被其他线程改写,本次未写入,调用者应决定是重试还是放弃。

这一"返回值即旧值"的语义与 CUDA 的atomicCAS保持一致,也使得atomic_cas可以天然地用来实现"只允许一个线程成功"的选举逻辑。

调用示例:多线程竞争下的唯一 Winner

以下示例来自 API 文档(与仓库端到端测试中的atomic_cas_winner_gm完全一致):32 个线程并发对state[0, 0]执行atomic_cas(state[0, 0], 0, 1),将old_values[0, tid]记录各自观察到的旧值。

import pypto_pro.language as pl @pl.vector_function(mode="simt", max_threads=32) def atomic_cas_winner_gm( state: pl.Tensor[[1, 1], pl.DT_INT32], old_values: pl.Tensor[[1, 32], pl.DT_INT32], ): tid = pl.simt.linear_thread_idx() old_values[0, tid] = pl.simt.atomic_cas(state[0, 0], 0, 1) @pl.jit() def simt_atomic_cas_winner_gm( state: pl.Tensor[[1, 1], pl.DT_INT32], old_values: pl.Tensor[[1, 32], pl.DT_INT32], ): with pl.section_vector(): atomic_cas_winner_gm32

运行逻辑推演:初始state[0, 0] == 0。32 个线程同时执行 CAS,最终只有一个线程能看到旧值0(等于compare),它把state写为1并成功;其余 31 个线程看到的旧值都是1(不等于compare),写入失败但state保持不变。因此最终state[0, 0] == 1,且old_values中恰好有一个0、其余为1——这正是"唯一 Winner 选举"的验证方式。

示例中两个值得注意的写法:

  • pl.simt.linear_thread_idx()获取当前线程的一维线性编号,用于区分每个线程写入old_values的列位置;
  • 外层pl.section_vector()将 SIMT 启动放入向量流水区域,atomic_cas_winner_gm32的方括号语法表示以 32 线程启动该 SIMT 函数。

源码级实现路径:从 Python API 到 CCE 指令

atomic_cas的完整调用链在仓库中可分为三层,理解这条路径有助于排查问题和二次开发:

1. Python DSL 层:API 声明

pypto_pro.language.simt.atomic_cas的声明位于 python/pypto_pro/language/_simt_api.py,通过@staticmethod+@_api_decl装饰器暴露给 DSL 前端。与atomic_addatomic_exchatomic_max等同族操作并列,构成完整的 SIMT 原子操作集合。

2. IR 构建层:容器 + 偏移的拆分

前端解析器将atomic_cas(tile[0, 0], compare, value)这种下标表达式拆解为"容器 + 偏移 + 操作数"三部分。IR 构建函数位于 python/pypto_pro/ir/op/simt_ops.py:

def atomic_cas(container, offset, compare, value, span=None): """Build an atomic compare-and-swap on one SIMT element.""" return _create_atomic_call("atomic_cas", container, offset, compare, value, span=span)

_create_atomic_call最终生成 IR 调用simt.atomic_cas(simt_ops.py),操作数顺序为[container, offset, compare, value]。AST 解析器通过@op_impl("simt.atomic_cas")注册(simt_ops.py),将源码中的调用语法映射到该 IR 节点——这也印证了文档"必须直接传下标表达式"的要求来自 IR 层的容器/偏移二元表示。

3. 后端代码生成层:映射到 atomicCAS

CCE 后端在 framework/src/interface/pypto_pro/backend/backend_cce_simt_ops.cpp 中把simt.atomic_cas映射为 CCE 内置函数:

if (op_name == "simt.atomic_cas") { return {"atomicCAS", 2}; }

并在同文件末尾注册该操作,指定其运行在S(标量)流水(backend_cce_simt_ops.cpp):

REGISTER_BACKEND_OP(BackendCCE, "simt.atomic_cas").set_pipe(ir::PipeType::S).f_codegen(MakeSimtAtomicCodegenCCE);

atomic_cas最终以标量原子指令的形式下发给 AICore,这也是其返回"单个旧值"而非批量结果的直接原因。

端到端测试验证:语义正确性的四重保障

仓库为atomic_cas提供了完整的 ST 测试(python/tests/st/pypto_pro/frontend/simt/atomic/test_atomic_cas.py),覆盖四个关键维度:

  1. UB Tile 全 dtype 测试test_atomic_cas_ub_all_supported_dtypes):对 DT_INT32、DT_UINT32、DT_FP32 三种 UB Tile 元素执行atomic_cas(..., 0, 7),断言最终值均为 7。注意 UB 用例需要先用pl.load把数据从 GM 搬入 UB Tile,并配合pl.system.sync_src/sync_dst做流水同步,最后pl.store写回。

  2. GM Tensor 全 dtype 测试test_atomic_cas_gm_all_supported_dtypes):覆盖 GM 侧全部五种 dtype(INT32/UINT32/FP32/INT64/UINT64),同样断言写 7 成功。

  3. 返回值与旁路元素保持测试test_atomic_cas_returns_old_value_and_preserves_other_elements):将state[0, 0]预置为 10,调用atomic_cas(state[0, 0], 10, 13),断言返回旧值 10 被写入old_values[0, 0]、目标元素变为 13,且同 Tensor 其他元素保持原值 123 不变——完整验证了"返回比较前旧值 + 仅修改目标元素"的语义。

  4. 竞争唯一 Winner 测试test_atomic_cas_contention_has_exactly_one_winner):32 线程竞争,断言最终state == 1old_values中恰好一个元素为 0、其余均为 1,从并发层面验证了原子性与"单次成功"保证。

此外,UT 层还有语法解析测试(python/tests/ut/pypto_pro/language/parser/test_simt_atomic.py)和 CCE 代码生成测试(python/tests/ut/pypto_pro/codegen/test_cce_simt.py),共同守护从语法解析到指令发射的全链路正确性。

使用建议与注意事项

  • 用返回值判断成败,不要依赖状态再检查:CAS 的成功判定应使用返回值与compare的比较,避免额外的读操作引入新的竞争窗口。
  • 整数目标不要传浮点字面量:如atomic_cas(state[0, 0], 0.0, 1.0)对 INT32 目标不合法,应写为01
  • UB 与 GM 的数据类型能力不同:UB Tile 仅支持 32 位三种类型;需要 64 位原子 CAS 时必须走 GM Tensor。
  • 仅在 SIMT 函数内使用atomic_cas依赖 SIMT 线程级并发,脱离mode="simt"的上下文调用不会被接受。
  • 配合流水同步使用:当atomic_cas作用于 UB Tile 时,写回 GM 前需通过pl.system.sync_*确保原子操作完成后才发起pl.store(参考 UB 测试用例的同步写法)。
  • 从源码阅读入口:接口语义见 python/pypto_pro/language/_simt_api.py,IR 构建见 python/pypto_pro/ir/op/simt_ops.py,CCE 发射见 framework/src/interface/pypto_pro/backend/backend_cce_simt_ops.cpp。

综上,atomic_cas为 PyPTO 的 SIMT 编程范式提供了底层、原子、可判定成败的同步原语,适用于跨线程计数、状态机迁移、唯一初始化等需要"比较-写回"一体的并发场景;结合文档、IR 源码与端到端测试,开发者可以放心地将其作为自旋锁与选举算法的地基。

  • 人工智能
  • 编译器
  • 模型编译
  • 高性能计算
  • 深度学习
  • CANN

【免费下载链接】pypto

PyPTO(发音: pai p-t-o):Parallel Tensor/Tile Operation编程范式。

项目地址:https://gitcode.com/cann/pypto
点击查看免费下载
上一篇:【亲测免费】 LibSU 开源项目教程
下一篇:FFUF 项目使用教程

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

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

GetQzonehistory 完整教程:免费导出 QQ 空间全部历史说说

GetQzonehistory 完整教程:免费导出 QQ 空间全部历史说说 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 免费 QQ 说说备份:跑完你能拿到什么 GetQzonehistory …

作者头像 李华
网站建设 2026/9/20 13:38:08

Zernike像差仿真:Matlab高精度建模与PSF物理映射

1. 为什么光学像差模拟不能只靠“画个圆圈加点波纹”?在光学系统设计、自适应光学调试、眼科波前像差分析这些实际场景里,我见过太多人用Photoshop手动叠加正弦纹理来“示意”像差——结果仿真数据和真实Zernike展开误差动辄30%以上,导致后续…

作者头像 李华
网站建设 2026/9/20 13:37:13

Design-Expert响应面法实战:从实验设计到配方优化全流程

简介:这份Design-Expert使用教程PDF面向科研人员、工程师和实验设计初学者,系统讲解响应曲面方法(RSM)在过程优化中的核心应用。内容从RSM基础概念出发,覆盖实验设计方案选择、数据分析与数学模型建立,并重…

作者头像 李华
网站建设 2026/9/20 13:36:06

el-select下拉框错位排查指南:从原理到实战修复方案

最近接手一个维护了三四年的后台管理系统,测试那边报了个挺典型的问题:页面里好几个el-select,点开以后下拉选项面板没有出现在输入框正下方,而是跑到了页面左上角,有的甚至悬在上一行表格的位置上。下拉框错位这个坑&…

作者头像 李华
网站建设 2026/9/20 13:34:30

EMC设计从玄学到工程:方法、分析与电路三位一体

简介:资源为一份聚焦电磁兼容性(EMC)方法、分析、电路设计和电缆屏蔽的英文PDF资源,面向电子设计工程师、硬件开发人员及EMC测试与认证人员。内容系统覆盖电磁兼容性测试方法、分析技术、电路设计原则,并重点讲解电缆耦…

作者头像 李华