news 2026/5/11 18:57:38

cann/asc-devkit L1到L0B转置数据搬运API

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
cann/asc-devkit L1到L0B转置数据搬运API

asc_copy_l12l0b_trans

【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit

产品支持情况

产品是否支持
Ascend 950PR/Ascend 950DT

功能说明

该接口实现带转置的2D格式数据从L1 Buffer到L0B Buffer的加载。

下面通过示例来讲解接口功能和关键参数:下文图中一个N形或者一个Z形代表一个分形。

  • 对于uint8_t/int8_t数据类型,每次迭代处理32 × 32 × 1B数据,可处理2个分形(一个分形512B),每次迭代中,源操作数中2个连续的16 × 32分形将被合并为1个32 × 32的方块矩阵,基于方块矩阵做转置,转置后分裂为2个16 × 32分形,根据目的操作数分形间隔等参数可以有不同的排布。

如下图示例:

  • 共处理3072B的数据,每次迭代处理32 × 32 × 1B数据,需要3次迭代可以完成,repeat_time = 3;
  • src_stride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:32 × 32 × 1B),这里的单位实际上是拼接后的方块矩阵的大小;
  • dst_gap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
  • dst_frac_gap = 0,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为0(单位:512B)。

如下图示例:

  • repeat_time和src_stride的解释和上图示例一致。

  • dst_gap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。

  • dst_frac_gap = 2,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为2(单位:512B)。

  • 对于half/bfloat16_t数据类型,每次迭代处理16 × 16 × 2B数据,可处理1个分形(一个分形512B),每次迭代中,源操作数中1个16 × 16分形将被转置。

    • 因为每次迭代处理16 × 16 × 2B数据,需要3次迭代可以完成,repeat_time = 3;
    • src_stride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1 (单位:16 × 16 × 2B);
    • dst_gap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址无间隔;
    • 该场景下,因为其分形即为方块矩阵,每个迭代处理一个分形,不存在迭代内分形的间隔,该参数设置无效。
  • 对于float/int32_t/uint32_t数据类型,每次迭代处理16 × 16 × 4B数据,可处理2个分形(一个分形512B),每次迭代中,源操作数2个连续的16 × 8分形将被合并为1个16 × 16的方块矩阵,基于方块矩阵做转置,转置后分裂为2个16 × 8分形,根据目的操作数分形间隔等参数可以有不同的排布。 如下图示例:

    • 因为每次迭代处理16 × 16 × 4B数据,需要3次迭代可以完成,repeat_time = 3;
    • src_stride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:16 × 16 × 4B),这里的单位实际上是拼接后的方块矩阵的大小;
    • dst_gap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
    • dst_frac_gap = 0,表示每个迭代内目的操作数前一个分形结束地址与后一个分形起始地址的间隔为0(单位:512B)。

如下图示例:

  • repeat_time和src_stride的解释和上图示例一致。

  • dst_gap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。

  • dst_frac_gap = 2,表示每个迭代内目的操作数前一个分形结束地址与后一个分形起始地址的间隔为2(单位:512B)。

  • 对于int4b_t数据类型,每次迭代处理64*64*0.5B数据,可处理4个分形(一个分形512B),每次迭代中,源操作数中4个连续的16*64分形将被合并为1个64*64的方块矩阵,基于方块矩阵做转置,转置后分裂为4个16*64分形,根据目的操作数分形间隔等参数可以有不同的排布。

    int4b_t数据类型需要两个数拼成一个int8_t或uint8_t的数,拼凑的规则如下:

    如下图所示:

    • 共需要处理6144B的数据,每次迭代处理64*64*0.5B数据,需要3次迭代可以完成,repeatTime = 3;
    • srcStride = 1,表示相邻迭代间,源操作数前一个方块矩阵与后一个方块矩阵起始地址的间隔为1(单位:64*64*0.5B),这里的单位实际上是拼接后的方块矩阵的大小;
    • dstGap = 1,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址到下一个迭代第一个分形起始地址的间隔为1(单位:512B);
    • dstFracGap = 0,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为0(单位:512B)。

    如下图示例:

    • repeatTime和srcStride的解释和上图示例一致。
    • dstGap = 0,表示相邻迭代间,目的操作数前一个迭代第一个分形的结束地址和下一个迭代第一个分形起始地址无间隔。
    • dstFracGap = 2,表示每个迭代内目的操作数前一个分形的结束地址与后一个分形起始地址的间隔为2(单位:512B)。

函数原型

  • 常规转置搬运

    __aicore__ inline void asc_copy_l12l0b_trans(__cb__ bfloat16_t* dst, __cbuf__ bfloat16_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ float8_e4m3_t* dst, __cbuf__ float8_e4m3_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ float8_e5m2_t* dst, __cbuf__ float8_e5m2_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ half* dst, __cbuf__ half* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ float* dst, __cbuf__ float* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ hifloat8_t* dst, __cbuf__ hifloat8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ int32_t* dst, __cbuf__ int32_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ int8_t* dst, __cbuf__ int8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ uint32_t* dst, __cbuf__ uint32_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ uint8_t* dst, __cbuf__ uint8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ fp4x2_e2m1_t* dst, __cbuf__ fp4x2_e2m1_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans(__cb__ fp4x2_e1m2_t* dst, __cbuf__ fp4x2_e1m2_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride);
  • 同步转置搬运

    __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ bfloat16_t* dst, __cbuf__ bfloat16_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ float8_e4m3_t* dst, __cbuf__ float8_e4m3_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ float8_e5m2_t* dst, __cbuf__ float8_e5m2_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ half* dst, __cbuf__ half* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ float* dst, __cbuf__ float* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ hifloat8_t* dst, __cbuf__ hifloat8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ int32_t* dst, __cbuf__ int32_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ int8_t* dst, __cbuf__ int8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ uint32_t* dst, __cbuf__ uint32_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ uint8_t* dst, __cbuf__ uint8_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ fp4x2_e2m1_t* dst, __cbuf__ fp4x2_e2m1_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride); __aicore__ inline void asc_copy_l12l0b_trans_sync(__cb__ fp4x2_e1m2_t* dst, __cbuf__ fp4x2_e1m2_t* src, uint16_t index_id, uint8_t repeat, uint16_t src_stride, uint16_t dst_stride, uint16_t dst_frac_stride, uint16_t src_frac_stride);

参数说明

参数名输入/输出描述
dst输出目的L0B Buffer地址。
src输入源L1 Buffer地址。
index_id输入矩阵ID,搬运起始位置为源操作数中第几个分形。取值范围:[0, 65535]。
repeat输入迭代次数。
对于位宽为4的数据类型,每次迭代处理4个分形,每个分形为16640.5B数据;
对于位宽为8的数据类型,每次迭代处理2个分形,每个分形为16321B数据;
对于位宽为16的数据类型,每次迭代处理1个分形,每个分形为16162B数据;对于位宽为32的数据类型,每次迭代处理4个分形,每个分形为1684B数据。取值范围:[1, 255]。
src_stride输入相邻迭代间,源操作数前一个分形与后一个分形起始地址的间隔。单位为单个分形512B。取值范围:[0, 65535]。
dst_stride输入相邻迭代间,目的操作数前一个分形与后一个分形起始地址的间隔。单位为单个分形512B。取值范围:[0, 65535]。
dst_frac_stride输入每个迭代内目的操作数转置前一个分形结束地址与后一个分形起始地址的间隔。单位为512B。仅在数据位宽为4、8或32时有效。
src_frac_stride输入每个迭代内源操作数转置前一个分形结束地址与后一个分形起始地址的间隔。单位为512B。仅在数据位宽为4、8或32时有效。

返回值说明

流水类型

PIPE_MTE1

约束说明

  • repeat=0表示不执行搬运操作。
  • 开发者需要保证目的操作数转置后的分形没有重叠。
  • 操作数地址重叠约束请参考通用地址重叠约束。

调用示例

//设置源操作数和目的操作数,total_length 指参与计算的数据长度 constexpr uint64_t total_length = 512; __cbuf__ int32_t src[total_length]; __cb__ int32_t dst[total_length]; // 设置搬运过程中的配置 uint8_t n = 64; uint8_t nBlockSize = 32; uint8_t repeat = n / nBlockSize; uint16_t index_id = 0; uint16_t src_stride = 1; uint16_t dst_stride = 1; uint16_t dst_frac_stride = 15; uint16_t src_frac_stride = 8; asc_copy_l12l0b_trans(dst, src, index_id, repeat, src_stride, dst_stride, dst_frac_stride, src_frac_stride);

【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言,原生支持C和C++标准规范,主要由类库和语言扩展层构成,提供多层级API,满足多维场景算子开发诉求。项目地址: https://gitcode.com/cann/asc-devkit

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

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

Chapter前端架构揭秘:Next.js与Apollo Client的完美结合

Chapter前端架构揭秘:Next.js与Apollo Client的完美结合 【免费下载链接】chapter A self-hosted event management tool for nonprofits 项目地址: https://gitcode.com/gh_mirrors/ch/chapter Chapter是一个开源的非营利组织活动管理工具,它采用…

作者头像 李华
网站建设 2026/5/11 18:52:49

如何快速突破百度网盘限速:开源工具的完整指南

如何快速突破百度网盘限速:开源工具的完整指南 【免费下载链接】baidupcs-web 项目地址: https://gitcode.com/gh_mirrors/ba/baidupcs-web 还在为百度网盘几十KB的龟速下载而烦恼吗?BaiduPCS-Web 是一款免费的开源解决方案,能让你轻…

作者头像 李华
网站建设 2026/5/11 18:50:37

【指南】零接触开卡:招商银行一网通账户线上申请全流程解析

1. 为什么需要线上申请招商银行一网通账户 最近几年,线上金融服务已经成为主流趋势。我身边不少朋友都遇到过这样的困扰:工作太忙没时间去银行网点,或者所在城市招商银行网点较少,甚至有些公司要求新员工远程入职时必须提供指定银…

作者头像 李华
网站建设 2026/5/11 18:49:13

保姆级教程:在银河麒麟Normal模式下,用kysec_set给第三方软件‘开绿灯’

银河麒麟系统下第三方软件安全授权全流程指南 在国产操作系统逐步普及的今天,银河麒麟作为主流选择之一,其安全机制设计严谨但有时也会给日常运维带来挑战。最近连续三个项目部署中,我都遇到了相同的问题——开发团队提供的工具包在测试环境运…

作者头像 李华
网站建设 2026/5/11 18:46:32

nuster部署最佳实践:从单机到集群的完整方案

nuster部署最佳实践:从单机到集群的完整方案 【免费下载链接】nuster A high performance HTTP proxy cache server and RESTful NoSQL cache server based on HAProxy 项目地址: https://gitcode.com/gh_mirrors/nu/nuster nuster是基于HAProxy的高性能HTTP…

作者头像 李华