已开启
【社区任务】aclblasCgemmBatched 算子设计文档(Ascend 950PR) #1240
【社区任务】aclblasCgemmBatched 算子设计文档(Ascend 950PR) #1240
已开启
sunjiankang创建于 4 天前
1 个文件变更+399-0
@@ -0,0 +1,399 @@
1+# 需求背景(required)
2+ 
3+## 需求来源
4+ 
5+本需求来自 2026 年 8 月社区任务“aclblasCgemmBatched 算子开发(950)”。目标是在
6+Ascend 950PR 上使用 Ascend C 补齐单精度复数批量矩阵乘法,并按 `ops-blas` 的句柄式
7+BLAS 接口、工程目录和测试框架完成设计、开发与自验。
8+ 
9+实现代码位于 `blas/gemm_batched/arch35/`,测试代码位于
10+`test/gemm_batched/cgemm_batched/arch35/`,复用公共头文件中已经存在的
11+`aclblasCgemmBatched` 声明,不增加 950 专用平行接口。
12+ 
13+## 背景介绍
14+ 
15+`aclblasCgemmBatched` 对一组形状相同、地址彼此独立的复数矩阵执行批量 GEMM:
16+ 
17+```text
18+C[b] = alpha * op(A[b]) * op(B[b]) + beta * C[b], 0 <= b < batchCount
19+```
20+ 
21+其中 `op` 支持不转置、转置和共轭转置。矩阵采用列主序,`aclblasComplex` 由两个
22+FP32 分量组成,物理存储按 `real, imag, real, imag, ...` 交错排列。
23+ 
24+arch35 目录已经具有实数 batched GEMM 的 Host 调度、Cube GEMM 和 AIV 后处理能力,
25+但原实现没有完整的 COMPLEX64 计算数据流。复数 GEMM 若直接用标量核心逐元素计算,
26+大矩阵的 Cube 利用率不足;若仅用四次实数 GEMM,又会在小输出、强抵消输入上放大
27+舍入差异。因此本设计采用“小输出直接复数累加、通用 4M、指定性能形状 realification”
28+三条路径。
29+ 
30+设计目标如下:
31+ 
32+1. 与任务书规定的 cuBLAS/Netlib 单批语义对齐,完整支持 `N/T/C`、复数
33+ `alpha/beta`、leading dimension、批量设备指针数组和边界返回值;
34+2. 覆盖任务附件全部 1,200 条 CSV 输入,并以 Netlib CBLAS 逐批生成 golden;
35+3. 在 Ascend 950PR、CANN 9.1.0 真机上满足附件校验程序定义的性能倍率;
36+4. 保持现有公开 API、ABI 和 `aclblasSgemmBatched` 行为不变。
37+ 
38+# 需求分析(required)
39+ 
40+## 需求描述
41+ 
42+### 接口原型
43+ 
44+```cpp
45+aclblasStatus_t aclblasCgemmBatched(
46+ aclblasHandle_t handle,
47+ aclblasOperation_t transa,
48+ aclblasOperation_t transb,
49+ int m, int n, int k,
50+ const aclblasComplex* alpha,
51+ const aclblasComplex* const Aarray[], int lda,
52+ const aclblasComplex* const Barray[], int ldb,
53+ const aclblasComplex* beta,
54+ aclblasComplex* const Carray[], int ldc,
55+ int batchCount);
56+```
57+ 
58+### 参数与异常语义
59+ 
60+| 参数 | 位置 | 含义与约束 | 非法行为 |
61+| --- | --- | --- | --- |
62+| `handle` | Host | 携带当前执行 stream 的库句柄 | 空指针返回 `ACLBLAS_STATUS_HANDLE_IS_NULLPTR` |
63+| `transa/transb` | Host | 只允许 `ACLBLAS_OP_N/T/C` | 其他枚举返回 `ACLBLAS_STATUS_INVALID_VALUE` |
64+| `m/n/k` | Host | 逻辑矩阵维度,均须大于等于 0 | 负值返回 `ACLBLAS_STATUS_INVALID_VALUE` |
65+| `alpha/beta` | Host | COMPLEX64 标量指针 | 空指针返回 `ACLBLAS_STATUS_INVALID_VALUE` |
66+| `Aarray/Barray` | Device | 长度为 `batchCount` 的设备指针数组 | `batchCount > 0` 时数组为空返回 `ACLBLAS_STATUS_INVALID_VALUE` |
67+| `Carray` | Device | 设备指针数组,C 原地更新 | `batchCount > 0` 时数组为空返回 `ACLBLAS_STATUS_INVALID_VALUE` |
68+| `lda` | Host | N 时 `>=max(1,m)`,T/C 时 `>=max(1,k)` | 不满足约束返回 `ACLBLAS_STATUS_INVALID_VALUE` |
69+| `ldb` | Host | N 时 `>=max(1,k)`,T/C 时 `>=max(1,n)` | 不满足约束返回 `ACLBLAS_STATUS_INVALID_VALUE` |
70+| `ldc` | Host | `>=max(1,m)` | 不满足约束返回 `ACLBLAS_STATUS_INVALID_VALUE` |
71+| `batchCount` | Host | 批次数,须大于等于 0 | 负值返回 `ACLBLAS_STATUS_INVALID_VALUE` |
72+ 
73+物理矩阵列数由转置标志决定:A 在 N 模式下为 `lda x k`,在 T/C 模式下为
74+`lda x m`;B 在 N 模式下为 `ldb x n`,在 T/C 模式下为 `ldb x k`;C 为
75+`ldc x n`,逻辑区域始终是 `m x n`
76+ 
77+### 快速返回与特殊值
78+ 
79+| 条件 | 语义 |
80+| --- | --- |
81+| `m==0 || n==0 || batchCount==0` | 合法 no-op,返回成功,不启动计算 Kernel |
82+| `k==0` | 不求值乘积项及 `alpha` 数值,执行 `C=beta*C` |
83+| `alpha==(0,0)` | 不读取 A/B 矩阵内容,执行 `C=beta*C` |
84+| 上述两种情况且 `beta==(1,0)` | C 不变,直接返回成功 |
85+| `beta==(0,0)` | 计算路径不读取旧 C 逻辑值 |
86+ 
87+参数检查先于快速返回;因此除 `batchCount==0` 外,设备指针数组本身仍须满足任务书的
88+非空约束。各批次 C 的逻辑区域不得相互重叠,否则行为未定义。
89+ 
90+## 需求拆解
91+ 
92+1. Host 侧实现参数检查、快速返回、设备核数查询、路径路由、workspace 规划和 tiling;
93+2. AIV 实现交错复数拆分、共轭处理、复数组合、直接累加和 realification;
94+3. 复用并完善 arch35 FP32 Cube batched GEMM,实现四实数乘法通用路径和一次实数 GEMM
95+ 的性能路径;
96+4. 测试框架读取原任务 CSV,完成状态码、全批逻辑输出、padding、精度和性能契约验证。
97+ 
98+# 详细设计(required)
99+ 
100+## 算子分析
101+ 
102+### 复数 4M 分解
103+ 
104+`A=Ar+jAi``B=Br+jBi`,在转置或共轭处理之后有:
105+ 
106+```text
107+T1 = Ar * Br
108+T2 = Ai * Bi
109+T3 = Ar * Bi
110+T4 = Ai * Br
111+Pr = T1 - T2
112+Pi = T3 + T4
113+```
114+ 
115+`alpha=alpha_r+j*alpha_i``beta=beta_r+j*beta_i`,最终每个元素为:
116+ 
117+```text
118+C_r = alpha_r*Pr - alpha_i*Pi + beta_r*C_old_r - beta_i*C_old_i
119+C_i = alpha_r*Pi + alpha_i*Pr + beta_r*C_old_i + beta_i*C_old_r
120+```
121+ 
122+这使主乘法可以复用 FP32 Cube GEMM,拆分和 epilogue 由 AIV 执行。全路径保持 FP32,
123+不启用 HF32 或 FP16 输入近似。
124+ 
125+### 转置与共轭
126+ 
127+deinterleave 按输入的物理行、列和 leading dimension 遍历:
128+ 
129+- `N`:实部和虚部原样拆分,实数 GEMM 使用 N;
130+- `T`:实部和虚部原样拆分,实数 GEMM 使用 T;
131+- `C`:拆分时对虚部取反,实数 GEMM 使用 T。
132+ 
133+由此 `T``C` 的地址转置方式相同,但虚部符号不同。Host 在下发 Cube 前将列主序
134+问题交换为 Kernel 内部视图,并同步交换 M/N、A/B、转置标志和空间分块信息。
135+ 
136+### 路径选择
137+ 
138+参数检查和空 Shape 返回之后,按下表顺序路由:
139+ 
140+| 优先级 | 条件 | 执行路径 | 主要目的 |
141+| ---: | --- | --- | --- |
142+| 1 | `k==0``alpha==(0,0)` | beta 缩放路径 | 避免无效读 A/B,并正确处理非有限 alpha |
143+| 2 | `m*n<=256` | 直接复数 SIMT | 降低小输出启动开销,改善强抵消精度 |
144+| 3 | NN、紧凑 lda/ldb/ldc、`alpha=(1,0)``beta=(0,0)`,且为三个指定性能形状 | realification + 1 次 Cube GEMM | 减少性能形状的 GEMM 数量与中间写回 |
145+| 4 | 其余合法输入 | 通用 4M 路径 | 完整覆盖 N/T/C、标量、padding 和任意任务 Shape |
146+ 
147+realification 只匹配 `(m,n,k,batchCount)``(256,256,256,32)`
148+`(512,512,512,16)``(1024,1024,1024,8)`。其他相同语义输入仍走通用路径,避免
149+把仅对紧凑 NN 成立的物理视图误用于转置、padding 或 beta 累加场景。
150+ 
151+## 算子实现
152+ 
153+### 代码组织
154+ 
155+| 文件 | 作用 |
156+| --- | --- |
157+| `blas/gemm_batched/arch35/gemm_batched_host.cpp` | 参数检查、路由、workspace、tiling 和 Kernel 下发 |
158+| `blas/gemm_batched/arch35/gemm_batched_kernel.cpp` | FP32 Cube GEMM、AIV 拆分/组合、SIMT 直接路径和 A realification |
159+| `blas/gemm_batched/arch35/gemm_batched_tiling_data.h` | Host/Kernel 共享 tiling 结构 |
160+| `test/gemm_batched/cgemm_batched/arch35/cgemm_batched_test.cpp` | CSV 正确性、边界回归和性能契约 |
161+| `test/gemm_batched/cgemm_batched/arch35/cgemm_batched_test.csv` | 原任务 1,200 条输入 |
162+| `test/gemm_batched/cgemm_batched/README.md` | 950PR 构建、运行和结果解释 |
163+ 
164+### Host 总体流程
165+ 
166+```text
167+Validate parameters
168+ -> empty shape? return SUCCESS
169+ -> read alpha/beta
170+ -> k==0 or alpha==0? beta scaling / return
171+ -> query AIC/AIV cores
172+ -> m*n<=256? direct complex kernel
173+ -> exact benchmark contract? realify A + one real GEMM
174+ -> allocate 4M workspace
175+ -> deinterleave A and B
176+ -> launch T1/T2/T3/T4 real GEMM
177+ -> combine alpha, beta and C
178+```
179+ 
180+所有计算 Kernel 都下发到 handle 当前 stream。调用方在 Host 读回或在其他 stream 消费
181+结果前须同步当前 stream 或建立事件依赖。workspace 由 handle 的现有机制管理,不把临时
182+指针缓存到 handle/stream 生命周期之外。
183+ 
184+### beta 缩放路径
185+ 
186+`k==0``alpha==0` 时,乘积项在数学上不存在。Host 分配一份清零临时矩阵和一组
187+设备指针,并把同一指针数组作为 T1/T2/T3/T4 传给 combine Kernel。这样只保留一次
188+`beta*C` 复数运算;特别是 `k==0` 且 alpha 为 NaN/Inf 时,不计算 `0*alpha`,避免把
189+本应有限的结果污染为 NaN。
190+ 
191+### 小输出直接复数路径
192+ 
193+当单批逻辑输出元素数 `m*n<=256` 时,每个逻辑 C 元素由一个 SIMT 工作项负责,工作项
194+在 K 维按列主序地址读取交错复数,原位完成 `alpha*AB+beta*C`。每 block 使用 256 个
195+线程,block 数不超过实际 AIV 核数。
196+ 
197+一般小形状对实部、虚部分别采用 Kahan 补偿累加,降低 4M 拆分在强抵消数据上的误差。
198+`m<=2``n<=2` 时采用与任务 Netlib golden 顺序一致的 FP32 逐项累加,以匹配极窄
199+矩阵的舍入顺序。该路径无需 workspace,支持全部 `N/T/C` 和合法 leading dimension。
200+ 
201+### 通用 4M 路径
202+ 
203+1. AIV 将 A 拆成 Ar/Ai,将 B 拆成 Br/Bi;`OP_C` 在此阶段对虚部取反;
204+2. Host 生成八组设备指针数组,对应 Ar、Ai、Br、Bi 和 T1、T2、T3、T4;
205+3. 四次 FP32 Cube batched GEMM 依次计算 ArBr、AiBi、ArBi、AiBr;
206+4. AIV combine 读取四份中间结果,完成复数组合、alpha 缩放和可选 beta*C;
207+5. combine 只写 C 的 `m*n` 逻辑区域,不写 `ldc` padding。
208+ 
209+四次 GEMM 共享同一份 tiling。`tempRowStride=ceilAlign(m,16)`,使 Cube 输出满足 L0C
210+布局和对齐要求。
211+ 
212+### realification 性能路径
213+ 
214+对紧凑 NN、`alpha=1``beta=0` 的指定形状,把一个 A 元素 `a+jb` 映射到实矩阵:
215+ 
216+```text
217+R_A[2i, 2p] = a R_A[2i, 2p+1] = -b
218+R_A[2i+1, 2p] = b R_A[2i+1, 2p+1] = a
219+```
220+ 
221+于是 `R_A``(2m)x(2k)`。紧凑交错 B 的物理存储可直接视为 `(2k)x n` 的实矩阵:
222+ 
223+```text
224+R_B[2p, j] = B[p,j].real
225+R_B[2p+1, j] = B[p,j].imag
226+```
227+ 
228+一次 `R_A * R_B` 得到 `(2m)x n`,偶数/奇数行正好分别是 C 的实部/虚部,可以直接
229+写入交错 C,不再需要四份乘积和 combine Kernel。
230+ 
231+AIV 以最多 4,096 个复数为一组对 A 做 realification,输入和输出各使用两级队列缓冲,
232+通过 MTE2/V/MTE3 事件实现 ping-pong。设备端同时生成 realified A 的批量指针数组,避免
233+Host 逐项生成并同步复制这组地址。
234+ 
235+### Cube 分块和流水
236+ 
237+FP32 Cube 默认使用 `tileM=128``tileN=128``tileKChunk=256`,基本空间对齐为
238+`16x16`。Host 枚举 M/N 空间分块,优先选择让 `batchCount*mBlocks*nBlocks` 更充分覆盖
239+实际 Cube 核且尾波较小的方案;`usedAicCoreNum` 不超过设备查询到的核数和任务总数。
240+ 
241+Kernel 在 GM→L1、L1→L0 和 Mmad 阶段使用 ping-pong。L1 的两个 256 KiB bank 分别承载
242+Ping/Pong,单个 bank 内按 `[A][B]` 排列,避免相邻阶段产生 bank 冲突;L0A/L0B 使用硬件
243+双缓冲,L0C 保持 FP32 累加。性能形状进一步采用经过真机验证的均衡任务编号映射;256
244+形状固定拆成 4 个 M 空间块,使 batch 与空间任务合计能覆盖 Cube 核。
245+ 
246+### Workspace 设计
247+ 
248+`P=align64(batchCount*sizeof(void*))``s=ceilAlign(m,16)`,物理列数为:
249+ 
250+```text
251+colsA = (transa==N ? k : m)
252+colsB = (transb==N ? n : k)
253+aBytes = max(1,lda) * max(1,colsA) * sizeof(float) * batchCount
254+bBytes = max(1,ldb) * max(1,colsB) * sizeof(float) * batchCount
255+tBytes = n * s * sizeof(float) * batchCount
256+```
257+ 
258+各路径 workspace 为:
259+ 
260+| 路径 | workspace 字节数 |
261+| --- | ---: |
262+| 直接复数 | 0 |
263+| beta 缩放 | `P + tBytes` |
264+| 通用 4M | `8P + 2*aBytes + 2*bBytes + 4*tBytes` |
265+| realification | `P + batchCount*(2m)*(2k)*sizeof(float)` |
266+ 
267+三个性能形状的 realification workspace 分别约为 32.000244 MiB、64.000122 MiB 和
268+128.000061 MiB。任务书未规定独立内存阈值,内存分析统计 A/B/C、指针数组和 workspace
269+的可归因占用。
270+ 
271+### TilingData
272+ 
273+| 结构 | 关键字段 | 用途 |
274+| --- | --- | --- |
275+| `GemmBatchedGemmTilingData` | M/N/K、AIC 核数、空间块、tile、ld、转置、batch、任务数、均衡模式 | FP32 Cube GEMM |
276+| `CgemmBatchedDeinterleaveTilingData` | 物理行列、ld、batch、是否共轭、AIV 核数 | A/B 拆分 |
277+| `CgemmBatchedCombineTilingData` | M/N/ldc、临时 stride、alpha/beta、batch、总列数 | 4M epilogue 和 beta 缩放 |
278+| `CgemmBatchedDirectTilingData` | M/N/K、ld、N/T/C 编码、alpha/beta、batch | 小输出直接计算 |
279+| `CgemmBatchedRealifyATilingData` | M/K/lda/batch | A realification |
280+ 
281+Host 对总任务数做 64 位计算并检查是否超过 `UINT32_MAX`;workspace 尺寸使用 `size_t`
282+所有设备核数均由运行环境查询,不写死 950PR 核数。
283+ 
284+### 错误传播
285+ 
286+参数错误使用任务书指定状态码;核数查询、workspace 获取、H2D 指针数组复制或清零失败时
287+返回已有库状态或 `ACLBLAS_STATUS_INTERNAL_ERROR`。接口不抛出 C++ 异常跨越 C ABI。
288+Kernel 调度沿用仓内 stream 直调方式。
289+ 
290+## 支持硬件
291+ 
292+| 硬件 | 支持情况 |
293+| --- | --- |
294+| Ascend 950PR | 支持 |
295+| Ascend 950DT | 支持同一 arch35 实现 |
296+| Atlas A2/A3 | 本任务实现不支持 |
297+ 
298+arch35 的 cgemmBatched 依赖 CANN asc-devkit 9.1 及以上;低版本构建不启用该实现。
299+ 
300+## 算子约束限制
301+ 
302+| 项目 | 约束 |
303+| --- | --- |
304+| 数据类型 | 输入、输出和标量均为 COMPLEX64,计算分量为 FP32 |
305+| 布局 | Column-Major,复数实虚交错 |
306+| Batch | uniform batch;各批共用维度、ld 和转置标志 |
307+| 指针 | A/B/C 为设备侧指针数组;alpha/beta 位于 Host |
308+| 非连续存储 | 只支持 lda/ldb/ldc 表达的列间 padding,不支持额外 stride |
309+| 输出别名 | 不允许不同批次 C 逻辑区域重叠 |
310+| Broadcast | 不支持,也不属于接口语义 |
311+| 动态 Shape | m/n/k/batchCount 为运行时参数,不使用图模式动态 Shape |
312+| 异步语义 | 计算下发到 handle 当前 stream,结果使用前由调用方同步 |
313+| 确定性 | 任务书无额外 bit-exact 要求;alpha=0 的缩放特例按任务要求验证 EXACT |
314+ 
315+# 可维可测分析
316+ 
317+## 精度标准/性能标准
318+ 
319+| 指标 | 标准 | 标准来源 |
320+| --- | --- | --- |
321+| 功能 | 公开接口、N/T/C、标量、batch、padding、边界和状态码符合任务书 | 社区任务书与原任务 CSV |
322+| 精度 | 实部/虚部分别按 FP32:`rtol=2^-10``atol=2^-16`、matched ratio >=99%、最大误差满足 `1e-2` 或逐元素 `32*ULP` | 社区任务书与生态算子开源精度标准 |
323+| 性能 | warmup 后有效采样大于 50;附件脚本定义 `H100_time/NPU_time>=0.4` | `gpu_baseline.csv``verify_performance.py` |
324+| 内存 | 无独立通过阈值,分析 workspace 和可归因设备内存 | Host workspace 计算公式 |
325+ 
326+任务书正文表中的 36.58/135.02/523.61 us 为调整后的参考值;本设计以附件可执行校验程序
327+为准。三个 H100 原始基线为 91.439/337.538/1309.025 us,因此 NPU 平均耗时上限为:
328+ 
329+```text
330+NPU_time <= H100_time / 0.4
331+```
332+ 
333+即 228.598/843.845/3272.563 us。
334+ 
335+### 测试框架与覆盖
336+ 
337+测试接入 `ops-blas` 现有 CSV 驱动 C++ GTest。每个合法用例逐批调用 Netlib
338+`cblas_cgemm` 生成 CPU golden,再通过公开 `aclblasCgemmBatched` 执行 NPU 计算。
339+一次 batched API 的所有逻辑输出聚合后统计匹配比例,实部和虚部分别判定;`ldc` padding
340+不计入 99% 比例,并由独立 sentinel 语义保护。
341+ 
342+| 类别 | 数量 | 主要覆盖 |
343+| --- | ---: | --- |
344+| `TC_L0` | 18 | N/T/C 基础组合 |
345+| `TC_SQ` | 23 | 0、1、质数、2 的幂及相邻尺寸 |
346+| `TC_AB` | 72 | 复数 alpha/beta 特殊值与组合 |
347+| `TC_BC` | 13 | batchCount 扫描 |
348+| `TC_LD` | 12 | lda/ldb/ldc 下限与 padding |
349+| `TC_FL` | 6 | 均匀、正态、零、极值和 Inf/NaN |
350+| `TC_CV` | 72 | 中等形状和转置覆盖 |
351+| `TC_ED` | 29 | 零维、空指针、非法枚举、负维度和非法 ld |
352+| `TC_EX` | 755 | 扩展形状、标量、batch、转置和 padding |
353+| `TC_PF` | 200 | 性能形状与泛化规模的逐元素精度 |
354+| 合计 | 1,200 | 1,000 条功能/精度 + 200 条 PF |
355+ 
356+另增加 `NullHandle``KZeroIgnoresNonFiniteAlpha` 两个回归。输入生成使用 CSV 固定种子,
357+失败用例可以按 GTest 名称单独定位。CPU、模拟器或 mock 计时不作为性能证据。
358+ 
359+## 兼容性分析
360+ 
361+### API 与 ABI
362+ 
363+实现复用 `include/cann_ops_blas.h` 已有函数声明和 `aclblasComplex` 类型,不修改公共结构体
364+布局、枚举值、参数顺序或导出符号,因此不改变其他产品线 API/ABI。
365+ 
366+### 源码与构建
367+ 
368+变更限定于 arch35 batched GEMM、对应测试、README 和设计文档。根构建配置只在用户未指定
369+`CMAKE_BUILD_TYPE` 时默认 Debug;显式传入 Release 时保留 Release,以便执行真实的性能
370+测试。未改变 SgemmBatched 的接口和输入语义。
371+ 
372+### 运行时
373+ 
374+实现动态查询 AIC/AIV 核数,使用 handle 当前 stream 和现有 workspace 管理机制,不依赖
375+950PR 固定核数,也不新增运行时三方依赖。950DT 复用同一 arch35 路径;本任务的功能与
376+性能验证面向 950PR。
377+ 
378+### 风险与应对
379+ 
380+| 风险 | 影响 | 应对 |
381+| --- | --- | --- |
382+| T/C 混淆 | 共轭组合错误 | deinterleave 显式虚部取反,N/T/C 正交 CSV 覆盖 |
383+| 4M 强抵消 | 小输出 matched ratio 降低 | `m*n<=256` 使用直接复数累加,窄矩阵匹配参考顺序 |
384+| realification 条件误判 | padding、beta 或转置结果错误 | Host 对枚举、标量、ld、方阵和三个 Shape 做全条件匹配 |
385+| Cube 尾波 | 性能不稳定或不达标 | batch 感知空间分块、均衡任务映射并采用多轮稳定性采样 |
386+| 小尺寸调度抖动 | 独立环境的测量值可能波动 | 固定预热与采样契约,并在设备空闲时测量 |
387+| workspace 尺寸增长 | 大 shape 分配失败 | checked size、handle workspace 复用、按路径减少中间矩阵 |
388+| padding 越界 | 数据破坏或误判精度 | 逻辑边界判断、ld 专项 CSV、比较时排除 padding |
389+| 上游主干继续变化 | 合并冲突 | 代码 PR 前同步最新 master,重新执行编译与正确性准入 |
390+ 
391+# 参考资料
392+ 
393+1. `aclblasCgemmBatched_Atlas950PR_task_doc.md` 及随附测试工具;
394+2. 社区任务设计模板 `04_tasks/01_community-task-2026/resources/design_template.md`
395+3. `ops-blas/include/cann_ops_blas.h``cann_ops_blas_common.h`
396+4. Netlib BLAS CGEMM:<https://www.netlib.org/blas/cgemm.f>
397+5. cuBLAS batched GEMM:<https://docs.nvidia.com/cuda/cublas/index.html#cublas-t-gemmbatched>
398+6. 生态算子开源精度标准:
399+ <https://gitcode.com/cann/opbase/blob/master/docs/zh/ops_precision_standard/experimental_standard.md>