| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat: 新增 aclsparseXcoo2csr 算子 Co-authored-by: yuyuanfeng<yuyuanfeng1@huawei.com> # message auto-generated for no-merge-commit merge: !78 merge feat-coo2csr into master feat: 新增 aclsparseXcoo2csr 算子 Created-by: yuyuanfeng Commit-by: yuyuanfeng Merged-by: cann-robot Description: ## 描述 新增 aclsparseXcoo2csr 算子,实现 COO 格式行索引数组到 CSR 格式行指针数组的转换。 **算子功能**:给定已按行非递减排序的 COO 行索引数组 cooRowInd[0..nnz-1],统计每行非零元素个数,再通过排他前缀和生成 CSR 行指针数组 csrRowPtr[0..m]。 **实现要点**: - 基于 Ascend950(DAV_3510)架构 SIMT 编程模型 - 行计数阶段采用游程编码(RLE)局部计数策略,减少原子竞争 - 前缀和阶段支持三级执行路径:融合 kernel(m/nnz <= 1024)、单核串行、多核并行(m > 1024,3 阶段:局部前缀和 → 块间归约 → 偏移修正) - 完整处理 m=0、nnz=0、0-based/1-based 索引基址等边界场景 - workspace 不足时返回 ACL_SPARSE_STATUS_INSUFFICIENT_RESOURCES,调用方须通过 aclsparseSetWorkspace 提供足够空间 **交付文件**(12 个): - 算子源码 5 个:sparse/coo2csr/arch35/ 下 host/kernel/tiling - 算子文档 1 个:sparse/coo2csr/README.md(按仓内模板 docs/zh/develop/readme_develop_guide.md 编写) - 测试代码 6 个:test/coo2csr/ 下测试用例、golden、参数、CSV - 公共头文件修改 1 个:include/cann_ops_sparse.h(+29 行 API 声明) ## 关联的Issue [#114](https://gitcode.com/cann/ops-sparse/issues/114) ## 测试 ST 测试 51/51 PASSED(41 功能 + 10 异常),覆盖以下场景: - 正常用例:多种矩阵规模(4×4 ~ 1048576×1)、不同稀疏度 - 边界用例:m=0、nnz=0(idxBase=0/1) - 索引基址:0-based 和 1-based 均覆盖 - 大规模矩阵:m > 1024 触发多核并行前缀和路径 - 小规模矩阵:m/nnz <= 1024 触发融合 kernel 路径 - 异常用例:null handle/pointer、负 nnz/m、无效 idxBase、workspace 不足、nnz==0+idxBase==1 直接 API 测试 ## 文档更新 新增 sparse/coo2csr/README.md,按仓内指导文档 docs/zh/develop/readme_develop_guide.md 编写,包含算子概述、接口列表、产品支持情况、接口详情(函数原型/参数说明/约束说明/边界行为)、支持的稀疏格式、调用示例(RAII 模式)。 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!78 | 1 个月前 | |
feat(arch35): 新增 aclsparseXcoosort COO 排序算子 Co-authored-by: chensi79<chensi79@huawei.com> # message auto-generated for no-merge-commit merge: !62 merge feat/aclsparse-xcoosort into master feat(arch35): 新增 aclsparseXcoosort COO 排序算子 Created-by: chensi79 Commit-by: chensi79 Merged-by: cann-robot Description: ## 描述 新增面向 Ascend950(arch35 / dav-3510)的 aclsparseXcoosort COO 坐标稳定排序能力。 - 新增 workspace 查询、ByRow 和 ByColumn 三个接口; - 原地重排 COO row/col,并输出排列数组 P; - 采用两趟 LSB RADIX_SORT 实现双键稳定排序; - nnz > 2048 时按 UB 容量生成多核 run,并通过 GM ping-pong、merge-path 完成稳定归并; - 适配主线目录重组,将实现集成到 sparse/coosort; ## 关联的Issue 关联 Issue:https://gitcode.com/cann/ops-sparse/issues/102 ## 测试 已通过: bash build.sh --ops=coosort --soc=ascend950 ops_sparseLt、ops_sparse、coosort_test 均构建成功。  readme示例代码执行成功  ## 文档更新 新增 coosort README,包含接口说明、约束、支持平台和调用示例;更新公共头文件接口声明。 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!62 | 1 个月前 | |
feat(arch35): 新增 aclsparseXcscsort CSC 排序算子 Co-authored-by: chensi79<chensi79@huawei.com> # message auto-generated for no-merge-commit merge: !80 merge feat/aclsparse-xcscsort into master feat(arch35): 新增 aclsparseXcscsort CSC 排序算子 Created-by: chensi79 Commit-by: chensi79 Merged-by: cann-robot Description: ## 描述 对齐 cuSPARSE cusparseXcscsort 接口,新增 CSC 格式按列内行索引稳定升序排序算子,同步重排置换向量 P。为仓内 csrsort 的列向对偶:按 CSC 列(cscColPtr 划分)对每列的 cscRowInd 做稳定升序排序,P 同步重排。 ### 算法设计 - **多核切分**:以累计 nnz 加权分配列区间,FindColBoundary 二分定位列边界,不拆分单列 - **单 run 路径**(len <= runSize):UB 内 Sort<int32_t>(RADIX_SORT) + Gather P + CopyOut - **多 run 路径**(len > runSize):Phase1 切多 run 各自 Sort 写入 GM scratch + merge-path 稳定归并 - **pBuffer 128 字节对齐检查**(对齐 cuSPARSE 约束,csrsort 无此检查) - **workspace**:2*nnz*sizeof(int32_t),布局 [scratchRowInd(nnz), scratchP(nnz)] ### 与 csrsort 的对偶差异 | 差异项 | csrsort | cscsort | |--------|---------|---------| | 压缩维度指针 | csrRowPtr (m+1) | cscColPtr (n+1) | | 待排序索引 | csrColInd | cscRowInd | | 多核二分定位 | FindRowBoundary | FindColBoundary | | segment 区间 | [csrRowPtr[row], ...) | [cscColPtr[col], ...) | | pBuffer 对齐检查 | 不检查 | 检查 128 字节对齐 | ## 关联的Issue 无 ## 测试 - **功能测试**:39 用例(L0 冒烟 2 + L1 功能 12 + L2 边界异常 16 + 白盒 9),全部 PASS - **精度标准**:int32 exact match,稳定性验证通过 - **白盒覆盖**:可测分支 40/40 = 100% - **性能对比**:与 csrsort 同规模 ±1% 以内,无回归 - **编译环境**:CANN 9.0.0 / Ascend950PR ## 文档更新 - 新增 sparse/cscsort/README.md:算子使用文档(接口、参数、约束、调用示例、算法说明) - 修改 docs/zh/api_list.md:登记 cscsort 接口并补充详情章节 - 修改 include/cann_ops_sparse.h:追加 aclsparseXcscsort* API 声明 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: ## 备注 csrgeam2 算子存在预存编译问题(aclrtMemsetD32Async 在 CANN 9.0.0 中未声明),与本 PR 无关,不影响 cscsort 的独立编译与测试。 See merge request: cann/ops-sparse!80 | 1 个月前 | |
feat: 新增 aclsparseXcsr2coo 算子 Co-authored-by: yuyuanfeng<yuyuanfeng1@huawei.com> # message auto-generated for no-merge-commit merge: !71 merge aclsparseCsr2coo into master feat: 新增 aclsparseXcsr2coo 算子 Created-by: yuyuanfeng Commit-by: yuyuanfeng Merged-by: cann-robot Description: ## 描述 新增 aclsparseXcsr2coo 算子,对齐 cuSPARSE cusparseXcsr2coo(Legacy API)。将 CSR 行偏移数组展开为 COO 行索引数组,支持 CSC→COO 复用。 Kernel 采用 SIMT+SIMD 混合路径:小行多行场景(m > 1 且 nnz/m≤128)走 SIMT 线程级并行直访 GM,大行或单行场景(m == 1 或 nnz/m>128)走 SIMD Duplicate+DataCopyPad 流水线。多核余数分配法切分。 接口严格对齐 cuSPARSE:X 前缀命名、handle==nullptr→NOT_INITIALIZED、stream==nullptr→默认stream、INSUFFICIENT_RESOURCES 返回码。 ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/110 ## 测试 81 用例全 PASS(58 参数化 + 23 TEST_F): - L0 基础功能 15 例、L1 大shape+边界 38 例、L2 路径切换边界 5 例 - TEST_F 覆盖 9 条错误码 + 2 条合法边界 + 6 条异常输入鲁棒性 + B1回归 + 确定性路径边界 + 多chunk + StreamNullptr - 精度比对:直接 int32 位级(符合 non_compute 二进制一致标准) - msprof 性能实测通过 ## 文档更新 - sparse/csr2coo/README.md:算子文档,按仓内模板 docs/zh/develop/readme_develop_guide.md 规范编写(API/参数/约束/支持的稀疏格式/调用示例) ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!71 | 1 个月前 | |
Feat: 新增 aclsparseCsr2cscEx2 算子 Co-authored-by: yuyuanfeng<yuyuanfeng1@huawei.com> # message auto-generated for no-merge-commit merge: !69 merge aclsparseCsr2cscEx2 into master Feat: 新增 aclsparseCsr2cscEx2 算子 Created-by: yuyuanfeng Commit-by: yuyuanfeng Merged-by: cann-robot Description: ## 描述 新增面向 Ascend950(arch35, DAV_3510 SIMT)的 aclsparseCsr2cscEx2 算子,实现 CSR → CSC 稀疏矩阵格式转换,等价于稀疏矩阵转置(CSC = CSR^T)。该接口为 Legacy API 中的 type-generic 接口,通过 valType 参数分发,支持 INT8 / FP16 / BF16 / FP32 四种数据类型。 ### 交付物清单 | 类别 | 文件 | 说明 | |------|------|------| | **头文件** | include/cann_ops_sparse.h | 新增 aclsparseAction_t 枚举、aclsparseCsr2CscAlg_t 枚举、aclsparseCsr2cscEx2_bufferSize 和 aclsparseCsr2cscEx2 声明 | | **Kernel 实现** | sparse/csr2csc_ex2/arch35/csr2csc_ex2_kernel.cpp | 五 Kernel SIMT 实现(CountCols / SumStripeHist / PrefixSum / StripeBase / Scatter) | | **Kernel 声明** | sparse/csr2csc_ex2/arch35/csr2csc_ex2_kernel.h | kernel_do 签名声明 | | **Host 实现** | sparse/csr2csc_ex2/arch35/csr2csc_ex2_host.cpp | 参数校验 + Kernel launch + workspace 管理 | | **TilingData** | sparse/csr2csc_ex2/arch35/csr2csc_ex2_tiling_data.h | 各 Kernel TilingData 结构体定义 | | **README** | sparse/csr2csc_ex2/README.md | 算子文档(接口说明 + 参数表 + 约束 + 调用示例) | | **测试** | test/csr2csc_ex2/ | 测试参数结构体、CPU golden 参考、NPU wrapper、CSV 用例表、GTest 测试 | ### 算法架构 采用五 Kernel 串行 SIMT 架构(DAV_3510 / arch35): 1. **CountCols**:多 Block grid-stride loop,asc_atomic_add 统计每个 stripe 的列直方图(写 stripeHist 而非直接写 colCount,消除跨 block atomic 竞争) 2. **SumStripeHist**:多线程并行对 stripeHist 按列求和,重建 colCount 3. **PrefixSum**:单 warp 32 线程并行 Blelloch scan(warp shuffle),exclusive prefix sum → cscColPtr 4. **StripeBase**:多 Block 按列并行,将各 stripe 列直方图转换为各 stripe 的私有写游标 5. **Scatter**:每 block 单线程按 k 升序顺序写入 cscRowInd/cscVal,保证列内行号升序(无需独立 Sort kernel) Workspace: bufferSize = (1 + stripeCount) × (n + 1) × sizeof(int32_t),其中 stripeCount = min(⌈nnz / 256⌉, AIV 核数)。 ## 关联的Issue [#109](https://gitcode.com/cann/ops-sparse/issues/109) ## 测试 ### 测试验收结果 | 项目 | 值 | |------|-----| | 总用例数 | 63(50 参数化 + 13 异常) | | 通过数 | 63 | | 通过率 | **100%**(Ascend950PR 实机) | ### 精度结果 | dtype | 结果 | 精度标准 | |-------|------|--------| | FP32 | 位精确 | EXACT | | FP16 | 位精确 | EXACT | | BF16 | 位精确 | EXACT | | INT8 | 位精确 | EXACT | ### 测试覆盖维度 | 维度 | 覆盖情况 | |------|--------| | 数据类型 | FP32 / FP16 / BF16 / INT8 | | copyValues | NUMERIC / SYMBOLIC | | idxBase | 0-based / 1-based | | 矩阵形状 | 方阵(1×1 到 4096×4096)、宽矩阵、高矩阵、单行、单列、极端(m=2^20) | | 稀疏度 | 极稀疏(0.99)、中等(0.5~0.7)、稠密(0.01~0.05) | | 边界 | m=0、n=0、nnz=0、空行、空列 | | 异常 | handle nullptr、非法 valType/copyValues/idxBase/alg/m/n/nnz | ## 文档更新 - sparse/csr2csc_ex2/README.md:算子功能说明、接口原型、参数表、约束、返回值 / 错误码、调用示例 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!69 | 1 个月前 | |
feat: 新增 aclsparseCsr2gebsr 算子(CSR→GEBSR 格式转换,Ascend950 arch35) Co-authored-by: cann-robot<cann@cann.team> Co-authored-by: yangzhenya<yangzhenya4@huawei.com> # message auto-generated for no-merge-commit merge: !106 merge feat/csr2gebsr into master feat: 新增 aclsparseCsr2gebsr 算子(CSR→GEBSR 格式转换,Ascend950 arch35) Created-by: m0_72281197 Commit-by: yangzhenya;cann-robot Merged-by: cann-robot Description: # Csr2gebsr算子 ## 算子概述 csr2gebsr 算子用于将 CSR(Compressed Sparse Row)格式的稀疏矩阵转换为 GEBSR(General Block Sparse Row)格式,即分块 CSR 格式。CSR 以单个非零元为单位存储,GEBSR 以 rowBlockDim × colBlockDim 的块为单位存储,全零块被跳过以实现压缩。参考 CUDA cusparse 的 cusparse<t>csr2gebsr 接口。 采用 Legacy 三步法 API(对标 cuSPARSE): 1. **bufferSize**:查询 workspace 大小(纯 Host 计算) 2. **Nnz**:计算 bsrRowPtrC 和非零块数 nnzb 3. **Convert**:填充 bsrColIndC + bsrValC dir 参数指定块内内存布局:ROW = 行主序,COLUMN = 列主序。 ### 支持数据类型 | 数据类型 | 精度版本前缀 | 元素大小 | |----------|-------------|----------| | float32 | S | 4B | | float16 | H | 2B | | bfloat16 | Bh | 2B | | int32 | I | 4B | ### 支持芯片 | 芯片型号 | NPU 架构 | 架构目录 | |----------|----------|----------| | Ascend 950 | dav-3510 | arch35 | ## 算子执行接口 算子共提供 9 个公开接口(Legacy 三步法,4 精度版本 × bufferSize + Convert,1 个类型无关 Nnz): | 接口 | 说明 | |------|------| | aclsparse{S\|H\|Bh\|I}csr2gebsr_bufferSize | 查询 workspace 大小(4 精度版本) | | aclsparseXcsr2gebsrNnz | 计算 bsrRowPtrC 和 nnzb(类型无关) | | aclsparse{S\|H\|Bh\|I}csr2gebsr | 执行 CSR→GEBSR 转换(4 精度版本) | ### aclsparseScsr2gebsr_bufferSize #### 产品支持情况 | 芯片型号 | 支持状态 | |----------|----------| | Ascend 950 | 支持 | #### 函数原型 cpp aclsparseStatus_t aclsparseScsr2gebsr_bufferSize( aclsparseHandle_t handle, aclsparseDirection_t dir, int m, int n, const aclsparseMatDescr_t descrA, const float *csrValA, const int *csrRowPtrA, const int *csrColIndA, int rowBlockDim, int colBlockDim, size_t *pBufferSizeInBytes); > aclsparseHcsr2gebsr_bufferSize / aclsparseBhcsr2gebsr_bufferSize / aclsparseIcsr2gebsr_bufferSize 参数相同,仅 csrValA 类型不同(const void* 或 const int*)。 #### 参数说明 | 参数 | 输入/输出 | 类型 | 说明 | |------|-----------|------|------| | handle | 输入 | aclsparseHandle_t | ops-sparse 库上下文句柄,不可为 nullptr | | dir | 输入 | aclsparseDirection_t | 块内内存布局(ROW 或 COLUMN) | | m | 输入 | int | 矩阵行数,m >= 0 | | n | 输入 | int | 矩阵列数,n >= 0 | | descrA | 输入 | aclsparseMatDescr_t | 输入矩阵描述符,type 必须为 GENERAL | | csrValA | 输入 | const float* | CSR 非零值数组(本函数不读取,可为 nullptr) | | csrRowPtrA | 输入 | const int* | CSR 行偏移数组,长度 m+1,m > 0 时不可为 nullptr | | csrColIndA | 输入 | const int* | CSR 列索引数组(本函数不读取,可为 nullptr) | | rowBlockDim | 输入 | int | 块行维度,> 0 | | colBlockDim | 输入 | int | 块列维度,> 0 | | pBufferSizeInBytes | 输出 | size_t* | 所需 workspace 字节数,不可为 nullptr | #### 约束说明 - m >= 0,n >= 0 - rowBlockDim > 0,colBlockDim > 0 - m、n、rowBlockDim、colBlockDim 各自 ≤ INT32_MAX/2 - mb × nb ≤ INT32_MAX(mb = ceil(m/rowBlockDim),nb = ceil(n/colBlockDim)) - descrA 的 matrixType 必须为 GENERAL,indexBase 必须为 ZERO 或 ONE - m > 0 时 csrRowPtrA 不可为 nullptr ### aclsparseXcsr2gebsrNnz #### 产品支持情况 | 芯片型号 | 支持状态 | |----------|----------| | Ascend 950 | 支持 | #### 函数原型 cpp aclsparseStatus_t aclsparseXcsr2gebsrNnz( aclsparseHandle_t handle, aclsparseDirection_t dir, int m, int n, const aclsparseMatDescr_t descrA, const int *csrRowPtrA, const int *csrColIndA, const aclsparseMatDescr_t descrC, int *bsrRowPtrC, int rowBlockDim, int colBlockDim, int *nnzTotalDevHostPtr, void *pBuffer); #### 参数说明 | 参数 | 输入/输出 | 类型 | 说明 | |------|-----------|------|------| | handle | 输入 | aclsparseHandle_t | ops-sparse 库上下文句柄,不可为 nullptr | | dir | 输入 | aclsparseDirection_t | 块内内存布局(ROW 或 COLUMN) | | m | 输入 | int | 矩阵行数,m >= 0 | | n | 输入 | int | 矩阵列数,n >= 0 | | descrA | 输入 | aclsparseMatDescr_t | 输入矩阵描述符 | | csrRowPtrA | 输入 | const int* | CSR 行偏移数组,长度 m+1,m > 0 时不可为 nullptr | | csrColIndA | 输入 | const int* | CSR 列索引数组,nnz > 0 时需提供合法指针 | | descrC | 输入 | aclsparseMatDescr_t | 输出矩阵描述符,不可为 nullptr | | bsrRowPtrC | 输出 | int* | 块行偏移数组,长度 mb+1,不可为 nullptr | | rowBlockDim | 输入 | int | 块行维度,> 0 | | colBlockDim | 输入 | int | 块列维度,> 0 | | nnzTotalDevHostPtr | 输出 | int* | 非零块数输出指针,不可为 nullptr | | pBuffer | 输入 | void* | workspace,不可为 nullptr | #### 约束说明 - 同 bufferSize 约束 - descrC 不可为 nullptr,matrixType 必须为 GENERAL - bsrRowPtrC 不可为 nullptr - nnzTotalDevHostPtr 不可为 nullptr(HOST 模式为 host 指针,DEVICE 模式为 device 指针) - pBuffer 不可为 nullptr - nnzTotalDevHostPtr 的指针类型必须与 aclsparseSetPointerMode 设置一致:HOST 模式传 host 指针(算子 D2H 回传 nnzb),DEVICE 模式传 device 指针(算子 D2D 回传) - 本 API 异步执行(on stream),调用方在调用 Convert 前须同步 stream 或读回 nnzb 确认 Nnz 完成 ### aclsparseScsr2gebsr #### 产品支持情况 | 芯片型号 | 支持状态 | |----------|----------| | Ascend 950 | 支持 | #### 函数原型 cpp aclsparseStatus_t aclsparseScsr2gebsr( aclsparseHandle_t handle, aclsparseDirection_t dir, int m, int n, const aclsparseMatDescr_t descrA, const float *csrValA, const int *csrRowPtrA, const int *csrColIndA, const aclsparseMatDescr_t descrC, float *bsrValC, int *bsrRowPtrC, int *bsrColIndC, int rowBlockDim, int colBlockDim, void *pBuffer); > aclsparseHcsr2gebsr / aclsparseBhcsr2gebsr / aclsparseIcsr2gebsr 参数相同,仅 csrValA/bsrValC 类型不同。 #### 参数说明 | 参数 | 输入/输出 | 类型 | 说明 | |------|-----------|------|------| | handle | 输入 | aclsparseHandle_t | ops-sparse 库上下文句柄,不可为 nullptr | | dir | 输入 | aclsparseDirection_t | 块内内存布局(ROW 或 COLUMN) | | m | 输入 | int | 矩阵行数,m >= 0 | | n | 输入 | int | 矩阵列数,n >= 0 | | descrA | 输入 | aclsparseMatDescr_t | 输入矩阵描述符 | | csrValA | 输入 | const float* | CSR 非零值数组,m > 0 时不可为 nullptr | | csrRowPtrA | 输入 | const int* | CSR 行偏移数组,长度 m+1,m > 0 时不可为 nullptr | | csrColIndA | 输入 | const int* | CSR 列索引数组,m > 0 时不可为 nullptr | | descrC | 输入 | aclsparseMatDescr_t | 输出矩阵描述符 | | bsrValC | 输出 | float* | GEBSR 非零块值数组,长度 nnzb×rowBlockDim×colBlockDim,m > 0 且 n > 0 时不可为 nullptr | | bsrRowPtrC | 输入/输出 | int* | 块行偏移数组,长度 mb+1,不可为 nullptr | | bsrColIndC | 输出 | int* | 块列索引数组,长度 nnzb,m > 0 且 n > 0 时不可为 nullptr | | rowBlockDim | 输入 | int | 块行维度,> 0 | | colBlockDim | 输入 | int | 块列维度,> 0 | | pBuffer | 输入 | void* | workspace,不可为 nullptr | #### 约束说明 - 同 Nnz 约束 - m > 0 时 csrValA、csrRowPtrA、csrColIndA 不可为 nullptr - m > 0 && n > 0 时 bsrValC、bsrColIndC 不可为 nullptr - m == 0 || n == 0 时跳过 kernel,直接返回 SUCCESS - 本 API 依赖前置 Nnz 已在 stream 上完成,调用方须在调用前同步 stream ### 返回值 | 返回值 | 说明 | |--------|------| | ACL_SPARSE_STATUS_SUCCESS | 操作成功 | | ACL_SPARSE_STATUS_HANDLE_IS_NULLPTR | handle 为 nullptr | | ACL_SPARSE_STATUS_INVALID_VALUE | 参数非法(负值、非法枚举、nullptr 指针、维度溢出) | | ACL_SPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED | 矩阵类型非 GENERAL | | ACL_SPARSE_STATUS_EXECUTION_FAILED | aclrt API 调用失败 | | ACL_SPARSE_STATUS_INTERNAL_ERROR | 内部错误(如获取核数失败) | ### workspace 计算公式 - workspace 大小 = (mb + 1 + mb×nb + aivCoreNum) × sizeof(int32_t) - workspace 布局:[nnzBlocksPerRow(mb) | nnzbDev(1) | marker(mb×nb) | segSum(aivCoreNum)] - mb = ceil(m / rowBlockDim),nb = ceil(n / colBlockDim) - aivCoreNum 为 AI Core 数量 ### 输入数据契约 调用方必须保证(Host 侧无法校验 device 数据内容): - CSR 行内列索引必须按升序排列(Convert 阶段依赖二分查找定位目标块) - csrColIndA 每个元素(减去 baseA 后)必须落在 [0, n) 区间内 ## 实现架构 采用 SIMT 三层结构(class-based Dispatcher + asc_vf_call 混合编程模式),共 3 个 kernel: 1. **Kernel 1 (Nnz CountBlocksPerRow)**:逐块行扫描 CSR 行,用 marker 数组标记非零块,统计每行非零块数 nnzBlocksPerRow。多核按块行 mb 切分并行。 2. **Kernel 2 (PrefixSum)**:将 nnzBlocksPerRow 做 exclusive prefix sum 生成 bsrRowPtrC,并回传 nnzb。 - mb ≤ 128(useBlocks == 1):退化串行路径,单 kernel O(mb) - mb > 128(useBlocks > 1):融合并行路径,单 kernel 内 Phase1→SyncAll→Phase2→SyncAll→Phase3 3. **Kernel 3 (Convert)**:遍历 CSR 非零元,用 marker 做 BinarySearch 定位目标块位置,填充 bsrColIndC 和 bsrValC(按 dir 指定的 ROW/COLUMN 方向排列块内数据)。 ## 调用示例 示例代码如下,仅供参考,具体编译和执行过程请参考编译与运行样例。 ```cpp #include "acl/acl.h" #include "cann_ops_sparse.h" #include <iostream> int main() { aclError aclRet; aclsparseStatus_t spRet; aclRet = aclInit(nullptr); if (aclRet != ACL_SUCCESS) { std::cerr << "aclInit failed: " << aclRet << std::endl; return 1; } aclRet = aclrtSetDevice(0); if (aclRet != ACL_SUCCESS) { std::cerr << "aclrtSetDevice failed" << std::endl; aclFinalize(); return 1; } aclrtStream stream = nullptr; aclrtCreateStream(&stream); aclsparseHandle_t handle = nullptr; aclsparseCreate(&handle); aclsparseSetStream(handle, stream); aclsparseSetPointerMode(handle, ACL_SPARSE_POINTER_MODE_HOST); // 4x4 CSR matrix: // 1 0 0 0 // 0 0 0 0 // 0 0 0 2 // 0 0 0 0 int m = 4, n = 4, nnz = 2; int rowBlockDim = 2, colBlockDim = 2; int h_csrRowPtr[] = {0, 1, 1, 1, 2}; int h_csrColInd[] = {0, 3}; float h_csrVal[] = {1.0f, 2.0f}; aclsparseMatDescr_t descrA = nullptr, descrC = nullptr; aclsparseCreateMatDescr(&descrA); aclsparseSetMatType(descrA, ACL_SPARSE_MATRIX_TYPE_GENERAL); aclsparseSetMatIndexBase(descrA, ACL_SPARSE_INDEX_BASE_ZERO); aclsparseCreateMatDescr(&descrC); aclsparseSetMatType(descrC, ACL_SPARSE_MATRIX_TYPE_GENERAL); aclsparseSetMatIndexBase(descrC, ACL_SPARSE_INDEX_BASE_ZERO); int *d_rowPtr = nullptr, *d_colInd = nullptr; float *d_csrVal = nullptr; aclrtMalloc((void**)&d_rowPtr, 5*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void**)&d_colInd, 2*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc((void**)&d_csrVal, 2*sizeof(float), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMemcpy(d_rowPtr, 5*sizeof(int), h_csrRowPtr, 5*sizeof(int), ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy(d_colInd, 2*sizeof(int), h_csrColInd, 2*sizeof(int), ACL_MEMCPY_HOST_TO_DEVICE); aclrtMemcpy(d_csrVal, 2*sizeof(float), h_csrVal, 2*sizeof(float), ACL_MEMCPY_HOST_TO_DEVICE); // Step 1: bufferSize size_t bufSize = 0; spRet = aclsparseScsr2gebsr_bufferSize(handle, ACL_SPARSE_DIRECTION_ROW, m, n, descrA, d_csrVal, d_rowPtr, d_colInd, rowBlockDim, colBlockDim, &bufSize); if (spRet != ACL_SPARSE_STATUS_SUCCESS) { std::cerr << "bufferSize failed" << std::endl; goto cleanup; } void *d_buffer = nullptr; aclrtMalloc(&d_buffer, bufSize, ACL_MEM_MALLOC_HUGE_FIRST); // Step 2: Nnz int mb = (m + rowBlockDim - 1) / rowBlockDim; int *d_bsrRowPtr = nullptr; aclrtMalloc((void**)&d_bsrRowPtr, (mb+1)*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST); int nnzb = 0; spRet = aclsparseXcsr2gebsrNnz(handle, ACL_SPARSE_DIRECTION_ROW, m, n, descrA, d_row See merge request: cann/ops-sparse!106 | 20 天前 | |
feat: add aclsparseSgtsvInterleavedBatch operator for Ascend950 (arch35) Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !46 merge aclsparseSgtsvInterleavedBatch into master feat: add aclsparseSgtsvInterleavedBatch operator for Ascend950 (arch35) Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 为 Ascend 950PR / Ascend 950DT(arch35)新增 aclsparseSgtsvInterleavedBatch 算子实现,支持批量求解多个独立的三对角线性方程组 **A^(k) · x^(k) = b^(k)**。 改动原因: - ops-sparse 库此前缺少三对角线性方程组直接求解器,无法覆盖科学计算 / PDE 离散化 / 隐式时间积分等场景的高频需求 - 需对齐 NVIDIA cuSPARSE cusparseSgtsvInterleavedBatch 的接口语义,补齐 CANN Ascend 950 系列稀疏计算能力 改动方法: - 新增对外接口 aclsparseSgtsvInterleavedBatch(主接口)与 aclsparseSgtsvInterleavedBatch_bufferSizeExt(workspace 查询),定义于 include/cann_ops_sparse.h - 基于 SIMT 模型实现 kernel(src/gtsv_interleaved_batch/arch35/):每 block 64 线程,每线程独立处理 1 个 batch;线程局部状态保持在寄存器中,跨行依赖不经过 workspace GM 读写 - 采用 Thomas 算法(algo=0),workspace 仅存 d'[i] 供 backward 阶段使用,b'[i] 原位覆写到 x - 重构测试框架(新增 test/frame/ 公共组件:csv_loader、test_common、test_main),适配 CSV 数据驱动的算子测试 - 新增完整算子文档 src/gtsv_interleaved_batch/README.md ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> - #88 ## 测试 <!--描述进行了哪些测试来验证你的改动。--> - 新增 test/gtsv_interleaved_batch/ 测试用例,基于 CSV 数据驱动(gtsv_interleaved_batch_test.csv),覆盖 m=1 / 多 batch / 边界值等场景 - 提供 golden 参考实现(gtsv_interleaved_batch_golden.h)对比 NPU 计算结果 - 在 Ascend 950 上验证正确性(详见 README 预期输出样例)  ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> - 新增 src/gtsv_interleaved_batch/README.md:包含算子概述、接口函数原型、参数说明、约束条件、调用示例及预期输出 - 更新 include/cann_ops_sparse.h:新增 aclsparseSgtsvInterleavedBatch 与 _bufferSizeExt 接口声明及 Doxygen 注释 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!46 | 1 个月前 | |
feat: 新增 Ascend 950 aclsparseXcsrsort 接口 Co-authored-by: chensi79<chensi79@huawei.com> # message auto-generated for no-merge-commit merge: !72 merge feat/aclsparse-xcsrsort into master feat: 新增 Ascend 950 aclsparseXcsrsort 接口 Created-by: chensi79 Commit-by: chensi79 Merged-by: cann-robot Description: ## 描述 新增 Ascend 950(arch35)CSRSORT 能力,提供 aclsparseXcsrsort_bufferSizeExt 和 aclsparseXcsrsort 两个 C 接口,用于查询 workspace 大小,以及对 CSR 矩阵每行的列索引执行原地稳定升序排序。排序过程中 csrRowPtr 保持不变,P 按照与 csrColInd 相同的稳定排列同步重排。 主要改动: 在公共头文件中增加两个 CSRSORT 接口声明,支持 int32 索引以及 base-0、base-1 CSR。 Host 侧实现参数校验、nnz == 0 快速返回和 2 * nnz * sizeof(int32_t) workspace 大小计算。独立 tiling 工具根据 AIV 核数、UB 容量和 AscendC Sort 临时空间动态计算启动核数及单 run 大小,并为 SIMT DCache 预留 32 KiB。Kernel 使用 handle 中的 stream 异步启动。 Kernel 侧按照累计 nnz 均衡分核,分割点对齐完整 CSR 行边界。各核负责的原数组和 workspace 区间互不重叠,无需核间同步。 短行在 UB 内使用 AscendC Sort 完成稳定排序,并根据 Sort 输出索引同步 Gather P。长行使用 SIMT bottom-up merge-path,从宽度 1 开始逐轮稳定归并。每个线程通过 co-rank 二分确定对应输出位置在左右 run 中消费的元素数,并将 csrColInd/P 作为绑定数据对直接从 GM 写入目标 GM。相同列索引优先选择左侧元素,以保持稳定性。各轮结果在原数组和 GM workspace 之间 ping-pong,必要时并行拷回原数组。 所有外层 core 统一发起一次 asc_vf_call,归并轮次之间使用 block 级内存栅栏和线程同步,不需要跨核同步。 新增独立 CPU golden 和 GTest 用例,覆盖基本排序、空行、已排序/逆序、重复列索引稳定性、非 identity P、base-1、空矩阵、单元素行、多小行、非均匀多核行分布、长行多轮 SIMT归并、百万 nnz 多核场景、runSize±1 边界、非 64 元素数量、随机中等规模、非 128 字节对齐 workspace,以及空指针和非法维度等异常参数。 补充公开 API 列表、算子 README 和设计文档,说明接口语义、workspace、算法、参数约束和测试范围。 ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/111 ## 测试 - 已新增 test/csrsort/arch35/csrsort_golden.h,使用 CPU 稳定排序生成独立期望结果。 - 已新增 test/csrsort/arch35/csrsort_test.cpp,包含功能、多核非均匀行、长行多 run、 runSize 边界、base-0/base-1、csrRowPtr 不变、稳定性、workspace 对齐及异常参数用例。 - Ascend 950 构建:bash build.sh --ops=csrsort --soc=ascend950,test通过。 - 长行多 run、多核非均匀行和 runSize 边界三项设备专项回归:3/3 通过。 - Ascend 950 设备完整回归:./build/test/csrsort/csrsort_test,退出码 0,27/27 通过。  readme示例代码调用成功  ## 文档更新 - 更新 include/cann_ops_sparse.h,增加接口声明和参数说明。 - 更新 docs/zh/api_list.md,增加接口索引和 API 详细说明。 - 新增 sparse/csrsort/README.md 和 sparse/csrsort/DESIGN.md。 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!72 | 1 个月前 | |
feat: 新增 arch35 DenseToSparse 算子 Co-authored-by: chensi79<chensi79@huawei.com> # message auto-generated for no-merge-commit merge: !90 merge feat/densetosparse-arch35 into master feat: 新增 arch35 DenseToSparse 算子 Created-by: chensi79 Commit-by: chensi79 Merged-by: cann-robot Description: ## 描述 新增面向 Ascend 950(arch35 / dav-3510)的 DenseToSparse 算子。 - 提供 GetBufferSize、Analysis、Convert 三阶段接口。 - 支持 CSR、CSC、COO 和 Blocked-ELL 输出格式。 - 支持 INT8、FP16、BF16、FP32,row-major/column-major, I32/I64 索引及 base-0/base-1。 - 补齐算子所需的 mutable CSR/CSC/COO/BLOCKED_ELL descriptor 创建与 Analysis 后输出指针绑定能力。 - 增加功能、异常、边界、Golden、白盒和 CUDA 语义探针测试。 ## 关联的Issue ## 测试 - 标准构建通过: bash build.sh --ops=densetosparse --soc=ascend950 - descriptor 目标在 -Werror --npu-arch=dav-3510 下编译通过。 - 最终测试二进制 SHA-256:5ac3456f...c54。 - 真 NPU 功能/精度测试 99/99 PASS,0 FAIL,0 SKIP,bitwise/exact, 0 mismatch。 - 白盒 WB-01~WB-20 全过;Kernel 目标分支 36/36, Host 可安全执行目标分支 28/28。 ## 文档更新 新增 sparse/densetosparse/README.md,说明接口、调用流程、格式语义、数据类型、 workspace、生命周期、错误码与调用示例;新增 test/densetosparse/TEST_CASES.md 记录测试覆盖。 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!90 | 1 个月前 | |
fix:删除多余的SpVecManager Co-authored-by: iuyi<202313350054@nuist.edu.cn> # message auto-generated for no-merge-commit merge: !95 merge fix/remove-spvecmanager into master fix:删除多余的SpVecManager Created-by: iuyi Commit-by: iuyi Merged-by: cann-robot Description: ## 描述 删除多余的SpVecManager ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/124 ## 测试 <!--描述进行了哪些测试来验证你的改动。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!95 | 1 个月前 | |
feat(arch35): gather Co-authored-by: iuyi<202313350054@nuist.edu.cn> # message auto-generated for no-merge-commit merge: !85 merge feat/gather into master feat(arch35): gather Created-by: iuyi Commit-by: iuyi Merged-by: cann-robot Description: ## 描述 新增 aclsparseGather 算子,实现从稠密向量中按稀疏向量的索引数组收集元素(X.values[i] = Y[X.indices[i] - idxBase])。 主要改动: - **算子实现**:新增 sparse/gather/arch35/ 目录,包含 host 调度、tiling 数据结构和 device kernel,支持 FP32/FP16/BF16/FP64 四种数据类型及 32I/64I 两种索引类型,支持 0-based 和 1-based 索引基址 - **API 声明**:在 include/cann_ops_sparse.h 中新增 aclsparseGather 接口声明 - **文档**:新增 sparse/gather/README.md 算子说明文档(含完整调用示例),并在 docs/zh/api_list.md 中补充接口描述 - **测试**:新增 GTest + CSV 驱动的测试用例(97 个),覆盖 L0/L1/L2 多档尺寸、全数据类型组合、非 2 幂次 vec_size 及边界条件 ## 关联的Issue 无 ## 测试 - 新增 test/gather/arch35/gather_test.csv,包含 97 个测试用例 - 覆盖 vec_size 从 1 到 50000,nnz 从 1 到全稠密 - 覆盖 FP32/FP16/FP64 × 32I/64I × ZERO/ONE 组合 - 包含非 2 幂次尺寸(3/5/10/50/100/300/768/1500/3000/6000/12000/25000/50000) - 测试环境 x86_64 Ubuntu 24.04.4 LTS CANN 9.1.0 ascend950 ## 文档更新 - 新增 sparse/gather/README.md:算子概述、接口说明、约束、数据类型支持及完整 C++ 调用示例 - 更新 docs/zh/api_list.md:接口列表表格新增 aclsparseGather 条目,接口详情新增完整说明 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!85 | 1 个月前 | |
feat(gebsr2gebsc): 新增 aclsparsegebsr2gebsc 算子 Co-authored-by: yangzhenya<yangzhenya4@huawei.com> # message auto-generated for no-merge-commit merge: !102 merge feat/gebsr2gebsc into master feat(gebsr2gebsc): 新增 aclsparsegebsr2gebsc 算子 Created-by: m0_72281197 Commit-by: yangzhenya Merged-by: cann-robot Description: # gebsr2gebsc算子 ## 算子概述 gebsr2gebsc 算子用于将 GEBSR(General Block Sparse Row)格式的稀疏矩阵转换为 GEBSC(General Block Sparse Column)格式。当将每个 block 视为标量时,该操作等价于 csr2csc:块稀疏模式被转置(block (i,j) -> (j,i)),但块内内存布局不变。参考 CUDA cusparse 的 cusparse<t>gebsr2gebsc 接口。 块值拷贝模式由 rowBlockDimC/colBlockDimC 与 rowBlockDimA/colBlockDimA 的关系决定: - **Direct copy**(rC==rA && cC==cA):块元素原样拷贝 - **Block transpose**(rC==cA && cC==rA):块元素转置 dirA 指定块内内存布局(ROW=行主序, COLUMN=列主序),输入输出布局不变。 ### 支持数据类型 | 数据类型 | 枚举值 | 元素大小 | |----------|--------|----------| | float32 | ACL_FLOAT | 4B | | float16 | ACL_FLOAT16 | 2B | | bfloat16 | ACL_BF16 | 2B | | int32 | ACL_INT32 | 4B | | int8 | ACL_INT8 | 1B | ### 支持芯片 | 芯片型号 | NPU 架构 | 架构目录 | |----------|----------|----------| | Ascend 950 | dav-3510 | arch35 | ## 算子执行接口 算子共提供 2 个公开接口(type-generic,通过 valType 参数支持多种数据类型): | 接口 | 说明 | |------|------| | aclsparseGebsr2gebsc_bufferSize | 查询 workspace 大小 | | aclsparseGebsr2gebsc | 执行 GEBSR→GEBSC 转换 | ### aclsparseGebsr2gebsc_bufferSize #### 产品支持情况 | 芯片型号 | 支持状态 | |----------|----------| | Ascend 950 | 支持 | #### 函数原型 cpp aclsparseStatus_t aclsparseGebsr2gebsc_bufferSize( aclsparseHandle_t handle, int mb, int nb, int nnzb, const void *bsrValA, const int *bsrRowPtrA, const int *bsrColIndA, int rowBlockDimA, int colBlockDimA, aclsparseDirection_t dirA, aclDataType valType, size_t *pBufferSizeInBytes); #### 参数说明 | 参数 | 输入/输出 | 类型 | 说明 | |------|-----------|------|------| | handle | 输入 | aclsparseHandle_t | ops-sparse 库上下文句柄,不可为 nullptr | | mb | 输入 | int | 块行数,mb >= 0 | | nb | 输入 | int | 块列数,nb >= 0 | | nnzb | 输入 | int | 非零块数,nnzb >= 0 | | bsrValA | 输入 | const void* | GEBSR 非零块值数组(本函数不读取,可为 nullptr) | | bsrRowPtrA | 输入 | const int* | 块行偏移数组,长度 mb+1(本函数不读取,可为 nullptr) | | bsrColIndA | 输入 | const int* | 块列索引数组,长度 nnzb(本函数不读取,可为 nullptr) | | rowBlockDimA | 输入 | int | 输入块行维,> 0 | | colBlockDimA | 输入 | int | 输入块列维,> 0 | | dirA | 输入 | aclsparseDirection_t | 块内内存布局(ROW 或 COLUMN) | | valType | 输入 | aclDataType | 数据类型(FP32/FP16/BF16/INT32/INT8) | | pBufferSizeInBytes | 输出 | size_t* | 所需 workspace 字节数,不可为 nullptr | #### 约束说明 - mb >= 0,nb >= 0,nnzb >= 0 - rowBlockDimA > 0,colBlockDimA > 0 - nb <= INT32_MAX - 1 - mb == 0 时 nnzb 必为 0,nb == 0 时 nnzb 必为 0 - valType 仅支持 ACL_FLOAT / ACL_FLOAT16 / ACL_BF16 / ACL_INT32 / ACL_INT8 - mb == 0 || nb == 0 || nnzb == 0 时 workspace 大小为 0 ### aclsparseGebsr2gebsc #### 产品支持情况 | 芯片型号 | 支持状态 | |----------|----------| | Ascend 950 | 支持 | #### 函数原型 cpp aclsparseStatus_t aclsparseGebsr2gebsc( aclsparseHandle_t handle, int mb, int nb, int nnzb, const void *bsrValA, const int *bsrRowPtrA, const int *bsrColIndA, int rowBlockDimA, int colBlockDimA, void *bscVal, int *bscColPtr, int *bscRowInd, int rowBlockDimC, int colBlockDimC, aclsparseAction_t copyValues, aclsparseIndexBase_t idxBase, aclsparseDirection_t dirA, aclDataType valType, void *pBuffer); #### 参数说明 | 参数 | 输入/输出 | 类型 | 说明 | |------|-----------|------|------| | handle | 输入 | aclsparseHandle_t | ops-sparse 库上下文句柄,不可为 nullptr | | mb | 输入 | int | 块行数,mb >= 0 | | nb | 输入 | int | 块列数,nb >= 0 | | nnzb | 输入 | int | 非零块数,nnzb >= 0 | | bsrValA | 输入 | const void* | GEBSR 非零块值数组,长度 nnzb*rowBlockDimA*colBlockDimA | | bsrRowPtrA | 输入 | const int* | 块行偏移数组,长度 mb+1 | | bsrColIndA | 输入 | const int* | 块列索引数组,长度 nnzb | | rowBlockDimA | 输入 | int | 输入块行维,> 0 | | colBlockDimA | 输入 | int | 输入块列维,> 0 | | bscVal | 输出 | void* | GEBSC 非零块值数组,长度 nnzb*rowBlockDimC*colBlockDimC | | bscColPtr | 输出 | int* | 块列偏移数组,长度 nb+1 | | bscRowInd | 输出 | int* | 块行索引数组,长度 nnzb | | rowBlockDimC | 输入 | int | 输出块行维,> 0 | | colBlockDimC | 输入 | int | 输出块列维,> 0 | | copyValues | 输入 | aclsparseAction_t | SYMBOLIC(仅结构)或 NUMERIC(结构+值) | | idxBase | 输入 | aclsparseIndexBase_t | 索引基址(0-based 或 1-based) | | dirA | 输入 | aclsparseDirection_t | 块内内存布局(ROW 或 COLUMN) | | valType | 输入 | aclDataType | 数据类型(FP32/FP16/BF16/INT32/INT8) | | pBuffer | 输入 | void* | workspace,大小由 bufferSize 接口查询 | #### 约束说明 - mb >= 0,nb >= 0,nnzb >= 0 - rowBlockDimA > 0,colBlockDimA > 0,rowBlockDimC > 0,colBlockDimC > 0 - nb <= INT32_MAX - 1 - nnzb + idxBase <= INT32_MAX - mb == 0 时 nnzb 必为 0,nb == 0 时 nnzb 必为 0 - 输出块维度必须满足 direct copy(rC==rA && cC==cA)或 transpose(rC==cA && cC==rA),否则返回 NOT_SUPPORTED - mb > 0 时 bsrRowPtrA 不可为 nullptr - nnzb > 0 时 bsrColIndA 不可为 nullptr - nnzb > 0 && NUMERIC 时 bsrValA 不可为 nullptr - bscColPtr 不可为 nullptr - nnzb > 0 时 bscRowInd 不可为 nullptr - nnzb > 0 && NUMERIC 时 bscVal 不可为 nullptr ### 返回值 | 返回值 | 说明 | |--------|------| | ACL_SPARSE_STATUS_SUCCESS | 操作成功 | | ACL_SPARSE_STATUS_HANDLE_IS_NULLPTR | handle 为 nullptr | | ACL_SPARSE_STATUS_INVALID_VALUE | 参数非法(负值、非法枚举、nullptr 指针、数据契约违反) | | ACL_SPARSE_STATUS_NOT_SUPPORTED | 不支持的 valType 或块维度组合 | | ACL_SPARSE_STATUS_INSUFFICIENT_RESOURCES | workspace 不足 | | ACL_SPARSE_STATUS_EXECUTION_FAILED | aclrt API 调用失败 | | ACL_SPARSE_STATUS_INTERNAL_ERROR | 内部错误(如获取核数失败) | ### workspace 计算公式 - workspace 大小 = (1 + stripeCount) × (nb + 1) × sizeof(int32_t) - stripeCount = min(ceil(nnzb/256), aivCoreNum, 16MB/((nb+1)×4)) - pBuffer 可为 nullptr,此时使用 handle 内置 workspace(需足够大) ### 实现架构 采用与 csr2csc_ex2 相同的五阶段 kernel 流水线(块级结构转换等价): 1. **CountCols**:遍历 bsrColIndA,原子加统计每 stripe 列直方图 2. **SumStripeHist**:对 stripeHist 按列求和重建 colCount 3. **PrefixSum**:单 warp 并行 exclusive prefix sum -> bscColPtr 4. **StripeBase**:stripe 直方图按列前缀和 -> 每 stripe 写游标基址 5. **Scatter**:每 block 单线程顺序 scatter 写 bscRowInd / bscVal(含块值 direct copy / transpose) ## 调用示例 示例代码如下,仅供参考,具体编译和执行过程请参考编译与运行样例。 cpp #include "acl/acl.h" #include "cann_ops_sparse.h" #include <iostream> #define CHECK_ACL(x) do { aclError __e = (x); if (__e != ACL_SUCCESS) { \ std::cerr << "ACL error " << __e << " at line " << __LINE__ << std::endl; return 1; } } while(0) int main() { CHECK_ACL(aclInit(nullptr)); CHECK_ACL(aclrtSetDevice(0)); aclrtStream stream; CHECK_ACL(aclrtCreateStream(&stream)); aclsparseHandle_t handle; if (aclsparseCreate(&handle) != ACL_SPARSE_STATUS_SUCCESS) return 1; aclsparseSetStream(handle, stream); int mb = 2, nb = 2, nnzb = 3; int rowBlockDimA = 2, colBlockDimA = 2; int bsrRowPtrA[] = {0, 2, 3}; int bsrColIndA[] = {0, 1, 1}; float bsrValA[] = {1,2,3,4, 5,6,7,8, 9,10,11,12}; int *d_rowPtr = nullptr, *d_colInd = nullptr; float *d_bsrVal = nullptr; CHECK_ACL(aclrtMalloc((void**)&d_rowPtr, 3*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL(aclrtMalloc((void**)&d_colInd, 3*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL(aclrtMalloc((void**)&d_bsrVal, 12*sizeof(float), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL(aclrtMemcpy(d_rowPtr, 3*sizeof(int), bsrRowPtrA, 3*sizeof(int), ACL_MEMCPY_HOST_TO_DEVICE)); CHECK_ACL(aclrtMemcpy(d_colInd, 3*sizeof(int), bsrColIndA, 3*sizeof(int), ACL_MEMCPY_HOST_TO_DEVICE)); CHECK_ACL(aclrtMemcpy(d_bsrVal, 12*sizeof(float), bsrValA, 12*sizeof(float), ACL_MEMCPY_HOST_TO_DEVICE)); int *d_bscColPtr = nullptr, *d_bscRowInd = nullptr; float *d_bscVal = nullptr; CHECK_ACL(aclrtMalloc((void**)&d_bscColPtr, 3*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL(aclrtMalloc((void**)&d_bscRowInd, 3*sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL(aclrtMalloc((void**)&d_bscVal, 12*sizeof(float), ACL_MEM_MALLOC_HUGE_FIRST)); size_t bufSize = 0; if (aclsparseGebsr2gebsc_bufferSize(handle, mb, nb, nnzb, d_bsrVal, d_rowPtr, d_colInd, rowBlockDimA, colBlockDimA, ACL_SPARSE_DIRECTION_ROW, ACL_FLOAT, &bufSize) != ACL_SPARSE_STATUS_SUCCESS) return 1; void *d_buffer = nullptr; if (bufSize > 0) CHECK_ACL(aclrtMalloc(&d_buffer, bufSize, ACL_MEM_MALLOC_HUGE_FIRST)); if (aclsparseGebsr2gebsc(handle, mb, nb, nnzb, d_bsrVal, d_rowPtr, d_colInd, rowBlockDimA, colBlockDimA, d_bscVal, d_bscColPtr, d_bscRowInd, rowBlockDimA, colBlockDimA, ACL_SPARSE_ACTION_NUMERIC, ACL_SPARSE_INDEX_BASE_ZERO, ACL_SPARSE_DIRECTION_ROW, ACL_FLOAT, d_buffer) != ACL_SPARSE_STATUS_SUCCESS) return 1; CHECK_ACL(aclrtSynchronizeStream(stream)); if (d_buffer) aclrtFree(d_buffer); aclrtFree(d_rowPtr); aclrtFree(d_colInd); aclrtFree(d_bsrVal); aclrtFree(d_bscColPtr); aclrtFree(d_bscRowInd); aclrtFree(d_bscVal); aclsparseDestroy(handle); aclrtDestroyStream(stream); aclrtResetDevice(0); aclFinalize(); return 0; } ## 编译与运行 bash # 编译算子包 bash build.sh --pkg --soc=ascend950 --ops=gebsr2gebsc # 运行测试 bash build.sh --soc=ascend950 --ops=gebsr2gebsc --run ## 测试覆盖 测试文件位于 test/gebsr2gebsc/,采用 GTest + CSV 参数化测试框架,在 Ascend950 真机全部通过。 ### 测试结构 | 文件 | 说明 | |------|------| | gebsr2gebsc_param.h | CSV 参数结构体 | | gebsr2gebsc_golden.h | CPU golden 计算(含 Eigen 交叉校验) | | arch35/gebsr2gebsc_test.csv | L0/L1 正确性用例 | | arch35/gebsr2gebsc_npu_wrapper.h | NPU 输入生成 / 类型映射 / 执行封装 | | arch35/gebsr2gebsc_test.cpp | GTest 主测试(含异常测试) | ### L0/L1 正确性测试 | 级别 | 覆盖维度 | |------|----------| | L0 | 基本功能:FP32/FP16/BF16/INT32/INT8 五类型 × direct copy/block transpose × ROW/COLUMN × SYMBOLIC/NUMERIC × base 0/1 | | L0 | 块维度:1×1 / 2×2 / 2×3 / 3×2 / 2×4 / 4×2 / 3×3 / 4×4 / 3×5 / 5×3 / 4×8 / 8×4 | | L0 | 边界:空矩阵 / 单块 / 全满 / 全空块 / 极宽/极高矩阵 | | L1 | 中等规模:64×64 ~ 128×128 × direct/transpose × ROW/COLUMN | | L1 | 高稀疏度:0.9 / 0.95 / 0.99 × 大矩阵 | | L1 | 大规模:256×256 × direct/transpose | ### L2 异常测试 | 测试类别 | 覆盖内容 | |----------|----------| | 空指针 | handle / pBufferSizeInBytes / bscColPtr 为 nullptr | | 非法维度 | mb < 0 / nnzb < 0 | | 非法块维度 | rowBlockDimA == 0 | | 非法枚举 | dirA 为非法值 | | 不支持组合 | 块维度不满足 direct copy 或 transpose | ### 数据类型覆盖 | 数据类型 | 用例数 | 说明 | |----------|--------|------| | FP32 | 123 | 主类型,覆盖全维度组合 | | FP16 | 12 | 含 transpose / 1-based / symbolic | | BF16 | 12 | 含 transpose / 1-based / symbolic | | INT32 | 12 | 含 transpose / 1-based / symbolic | | INT8 | 12 | 含 transpose / 1-based / symbolic | # See merge request: cann/ops-sparse!102 | 23 天前 | |
Feat: 新增 aclsparseSgpsvInterleavedBatch 五对角批量求解接口(Ascend950/arch35) Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !55 merge aclsparseSgpsvInterleavedBatch into master Feat: 新增 aclsparseSgpsvInterleavedBatch 五对角批量求解接口(Ascend950/arch35) Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 描述 新增 aclsparseSgpsvInterleavedBatch 接口,实现面向 Ascend950(arch35)的五对角批次线性方程组求解。 **算子功能**:批量求解五对角线性方程组 A^(k) · x^(k) = b^(k),其中 A^(k) 为 m×m 五对角矩阵,由 5 条对角线(ds, dl, d, du, dw)定义,数据布局为 row-major interleaved。 **目标芯片**:Ascend950(A5 架构,arch35) **编程模型**:SIMT — 每线程处理 1 个 batch 的完整 m 行扫描,batch 间无数据依赖,通过 grid-stride 支持 batchCount 超过硬件核心数的场景。 **算法**:QR 分解 **接口列表**: - aclsparseSgpsvInterleavedBatch — 求解接口(FP32) - aclsparseSgpsvInterleavedBatch_bufferSizeExt — 工作区大小查询接口 ## 关联 Issue: <!-- Issue 提交后补充链接,格式:[#N](https://gitcode.com/cann/ops-sparse/issues/N) --> https://gitcode.com/cann/ops-sparse/issues/96 ## 测试 **测试框架**:GTest + CSV 参数化 **测试用例**:共 54 条,全部通过 - 正向用例:35条(L0 12 条 + L1 24 条) - 异常用例:19 条(nullptr / 非法参数 / 对齐错误等)  ## 文档更新 - **新增** src/gpsv_interleaved_batch/README.md — 算子接口文档(概述、接口签名、参数说明、约束、调用示例、LU 算法附录) - **修改** include/cann_ops_sparse.h — 追加 gpsv section 接口声明 - **新增** test/frame/fill.h — 追加约 100 行 Pentadiag 矩阵生成器(五对角填充 helper) ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!55 | 1 个月前 | |
feat(gtsv2): 将gtsv2测试脚本切换至混合容差标准并重构测试样例 Co-authored-by: Twoliges<202383290096@nuist.edu.cn> # message auto-generated for no-merge-commit merge: !86 merge feat/make-gtsv2-meet-standard into master feat(gtsv2): 将gtsv2测试脚本切换至混合容差标准并重构测试样例 Created-by: Twoliges Commit-by: Twoliges Merged-by: cann-robot Description: ## 描述 将 gtsv2 算子测试脚本切换至混合容差(MIXED_TOLERANCE)标准,并重构测试样例,使其符合 opbase 仓库精度标准文档下的 Tensor 生成规则。 ### 改动原因 仓库测试框架已引入 MIXED_TOLERANCE 精度策略(test/frame/verify.h),用于统一各算子的 精度容差判定。gtsv2 测试脚本仍使用旧的 per-case 手动容差配置(CSV 中每行指定 rtol/atol/mareMultiplier),与框架策略不一致,且 Tensor 生成规则与精度标准文档存在偏差。 ### 改动方法 仅涉及 gtsv2 测试侧 3 个文件,不改动 kernel / host / tiling: | 文件 | 改动 | |------|------| | test/gtsv2/gtsv2_param.h | 移除 rtol/atol/mareMultiplier 字段及 fillCustom 解析 | | test/gtsv2/arch35/gtsv2_test.csv | 表头移除容差三列;值域统一 ±5.0;用例覆盖 L0/L1/L2/WB | | test/gtsv2/arch35/gtsv2_test.cpp | 容差判定改为 applyMixedTolerance;RHS 生成值域对齐 | 容差判定流程变更: - 旧:CSV per-case 配置 → 手动 cfg.SetAbsTol/SetMERE/SetMARE - 新:框架级 applyMixedTolerance(cfg, ACL_FLOAT, golden, size) 自动按 dtype 选取默认容差 ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/118 ## 测试 ### 环境 - 硬件:Ascend 950(dav-3510 / arch35) - CANN:9.0.0-beta.2 - 编译模式:Release(CMAKE_BUILD_TYPE=Release) ### 测试命令 bash CMAKE_BUILD_TYPE=Release bash build.sh --ops=gtsv2 --run --soc=ascend950 ### 测试结果 [==========] 67 tests from 2 test suites ran. [ PASSED ] 67 tests. [PASS] gtsv2_test 全部 67 个用例通过(19 个异常测试 + 48 个计算测试),覆盖: - L0:基本功能(m ≤ 32,含对角占优 / 随机主元 / 单位矩阵退化) - L1:规模与边界(3×1 ~ 16384×2,含 ldb > m / 大 n 向量类 / 2 幂与非 2 幂) - L2:奇异矩阵(Inf/NaN 传播) - WB:主元交换路径(全交换 / 首步交换 / 末步交换 / 极端主元比 / block 尾线程) ## 文档更新 无需额外文档更新。gtsv2 算子 README 在此前提交中已创建,本次仅改测试脚本。 ## 类型标签 - [ ] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [x] 其他,请描述:测试脚本对齐精度标准 See merge request: cann/ops-sparse!86 | 1 个月前 | |
feat(arch35): 新增面向arch35的aclsparseSgtsv2Nopivot Co-authored-by: LuckySun<sunwenlong8@huawei.com> # message auto-generated for no-merge-commit merge: !64 merge aclsparseSgtsv2Nopivot into master feat(arch35): 新增面向arch35的aclsparseSgtsv2Nopivot Created-by: LuckySun Commit-by: LuckySun Merged-by: cann-robot Description: ## 描述 新增 aclsparseSgtsv2Nopivot 接口,用于求解三对角线性方程组(无选主元),支持多个右端项(Multiple RHS)。采用 SIMT 编程模型的 Thomas 消去法。 ### 实现要点 - 每 thread 直接读写 GM,处理一个 RHS 列(前向消去 + 后向回代) - 多核沿 RHS 列数 n 维度分布(grid-stride),numBlocks 按 ceil(n / 32) 计算 - workspace 大小:m × n × sizeof(float),128 字节对齐 - 数据布局:dl/d/du 为 [m],B 为 column-major [ldb × n] ### 变更文件 | 文件 | 说明 | |------|------| | include/cann_ops_sparse.h | 新增 aclsparseSgtsv2Nopivot 和 _bufferSizeExt 接口声明 | | sparse/gtsv2_nopivot/arch35/*.cpp/*.h | 算子源码(host + kernel + tiling) | | sparse/gtsv2_nopivot/README.md | 算子 README(接口签名、参数说明、调用示例) | | test/gtsv2_nopivot/* | ST 测试(29 计算 + 15 异常用例) | ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/104 ## 测试 - 全部通过:44/44(29 计算 + 15 异常),GTest + CSV 参数化框架 - 计算用例覆盖:m=3~16384, n=1~100000, ldb=m 和 ldb>m, 多种对角线构造(对角占优/单位阵/常数对角/随机对角) - 异常用例覆盖:handle/nullptr/m/n/ldb 违规 15 种场景 - 验证方式:MERE_MARE 模式,FP64 Thomas 算法作为 golden 参考 ## 文档更新 - 新增 sparse/gtsv2_nopivot/README.md ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!64 | 1 个月前 | |
feat: 新增 aclsparseSgtsv2StridedBatch 算子(支持 Ascend 950) Co-authored-by: yuyuanfeng<yuyuanfeng1@huawei.com> # message auto-generated for no-merge-commit merge: !57 merge aclsparseSgtsv2StridedBatch into master feat: 新增 aclsparseSgtsv2StridedBatch 算子(支持 Ascend 950) Created-by: yuyuanfeng Commit-by: yuyuanfeng Merged-by: cann-robot Description: ## 描述 新增 aclsparseSgtsv2StridedBatch 算子,批量求解三对角线性方程组 A^(i) y^(i) = x^(i)。 - **算法**:Cyclic Reduction 紧凑化变体,无选主元;两级架构——外层 GM 分块 CR + 内层 UB CR - **架构**:arch35 (Ascend950/DAV_3510),SIMD AIV only,KERNEL_TYPE_AIV_ONLY - **精度**:FP32(S 前缀),MERE_MARE 模式,MERE < 1.22e-4,MARE < 1.22e-3 - **支持范围**:m ∈ [3, 2^30] - 纯 UB 路径(m ≤ 2048):全数据驻留 UB,bufferSizeExt 返回 0 - 外层 GM 分块 CR 路径(2048 < m ≤ 2^30):外层在 GM 中按 tile 逐层归约到 2048 后,走内层 UB CR;workspace 按 batch 隔离(≈40×m_pad 字节/batch),经 bufferSizeExt 查询 - m 上限 2^30 为 int32 batchStride ≥ m_pad 契约的天花板(非算法上限),实际上限受 GM 内存约束 **接口**(Legacy API 体系,扁平参数): - aclsparseSgtsv2StridedBatch — 主接口,原地求解 y 覆盖 x - aclsparseSgtsv2StridedBatch_bufferSizeExt — workspace 大小查询 **关键设计**: - 多核按 batchCount 切分(base + remainder 均摊),单 batch 不跨核,核数通过 GetAivCoreCount() 动态获取 - Gather/Scatter Vector API,偏移表预计算跨 batch 复用 - 外层 GM 分块 CR:tile 化依赖分析(输出 j 仅依赖偶 2j/2j+2、奇 2j+1),单缓冲 staging + PipeBarrier 保证跨 pipe 同步 - 内外层衔接点恒为 2048(2^11):内层几何参数为常量(m_pad=2048、11 层归约),UB 占用与 m 规模解耦 ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/98 ## 测试 **测试通过率:95/95(100%)**(Ascend950PR 实机) | 类别 | 数量 | 说明 | |------|------|------| | L0 基础用例 | 11 | m=4/8/16/64/128/256,well_cond/diag_dom/const_diag | | L1 边界/多样性/批量压力用例 | 40 | 非 2 幂、batchCount=0、stride padding、mixed_sign/extreme_val/singular、batchCount=100~100000 | | L1 m 无上限外层 GM 分块 CR 用例 | 15 | m=4095/4097/5000/8192/65536/65537/1000003,含 m==m_pad 直读分支、多 batch 隔离、stride padding | | 异常用例 E1-E27 | 29 | 参数校验 + pBuffer 对齐 + bufferSizeExt 语义 + m>2^30 拒绝 | **Golden 参考**:Thomas 算法(TDMA)FP64 **精度偏差说明**:用例 L1_m1000003(mPad=2^20,20 层 CR 归约)MARE 判据为 15×2^-13(其余 94 条均为 10×2^-13,MERE 判据不变)。原因:无选主元 CR 在 20 层归约深度下的固有 FP32 噪声,3/1000003 个近零相消分量(|golden|≈1e-4)相对误差 1.6e-3、绝对误差仅 1~3 ulp(O(1) 解尺度);与 kernel 同公式同次序的 CPU FP32 CR 参考在相同索引复现相同 outlier(2/3 逐位一致),证明误差源自算法而非实现。 **性能(Gather/Scatter 优化,ACL Event)**: | m | batchCount | 耗时 (μs) | |---|-----------|-----------| | 64 | 10,000 | 35,900 | | 256 | 10,000 | 46,513 | | 1024 | 10,000 | 57,735 | 外层 GM 分块 CR 路径为带宽受限设计(≈32×m_pad floats GM 流量/batch),大 m 用例已在 ST 中完成功能验证。 ## 文档更新 - sparse/gtsv2_strided_batch/README.md:算子说明 + 纯 UB / 外层 GM 分块 CR 两种调用示例(示例已提取编译并在 Ascend950PR 实机运行验证,输出与文档一致) ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 代码重构 - [ ] 文档更新 - [ ] 其他 ## 自查清单 - [x] 代码通过编译 - [x] 测试用例全部通过(95/95) - [x] 已添加/更新相关文档 - [x] 提交信息符合规范 See merge request: cann/ops-sparse!57 | 1 个月前 | |
Feat: 新增 aclsparseSgpsvInterleavedBatch 五对角批量求解接口(Ascend950/arch35) Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !55 merge aclsparseSgpsvInterleavedBatch into master Feat: 新增 aclsparseSgpsvInterleavedBatch 五对角批量求解接口(Ascend950/arch35) Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 描述 新增 aclsparseSgpsvInterleavedBatch 接口,实现面向 Ascend950(arch35)的五对角批次线性方程组求解。 **算子功能**:批量求解五对角线性方程组 A^(k) · x^(k) = b^(k),其中 A^(k) 为 m×m 五对角矩阵,由 5 条对角线(ds, dl, d, du, dw)定义,数据布局为 row-major interleaved。 **目标芯片**:Ascend950(A5 架构,arch35) **编程模型**:SIMT — 每线程处理 1 个 batch 的完整 m 行扫描,batch 间无数据依赖,通过 grid-stride 支持 batchCount 超过硬件核心数的场景。 **算法**:QR 分解 **接口列表**: - aclsparseSgpsvInterleavedBatch — 求解接口(FP32) - aclsparseSgpsvInterleavedBatch_bufferSizeExt — 工作区大小查询接口 ## 关联 Issue: <!-- Issue 提交后补充链接,格式:[#N](https://gitcode.com/cann/ops-sparse/issues/N) --> https://gitcode.com/cann/ops-sparse/issues/96 ## 测试 **测试框架**:GTest + CSV 参数化 **测试用例**:共 54 条,全部通过 - 正向用例:35条(L0 12 条 + L1 24 条) - 异常用例:19 条(nullptr / 非法参数 / 对齐错误等)  ## 文档更新 - **新增** src/gpsv_interleaved_batch/README.md — 算子接口文档(概述、接口签名、参数说明、约束、调用示例、LU 算法附录) - **修改** include/cann_ops_sparse.h — 追加 gpsv section 接口声明 - **新增** test/frame/fill.h — 追加约 100 行 Pentadiag 矩阵生成器(五对角填充 helper) ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!55 | 1 个月前 | |
feat: add aclsparseSgtsvInterleavedBatch operator for Ascend950 (arch35) Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !46 merge aclsparseSgtsvInterleavedBatch into master feat: add aclsparseSgtsvInterleavedBatch operator for Ascend950 (arch35) Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> 为 Ascend 950PR / Ascend 950DT(arch35)新增 aclsparseSgtsvInterleavedBatch 算子实现,支持批量求解多个独立的三对角线性方程组 **A^(k) · x^(k) = b^(k)**。 改动原因: - ops-sparse 库此前缺少三对角线性方程组直接求解器,无法覆盖科学计算 / PDE 离散化 / 隐式时间积分等场景的高频需求 - 需对齐 NVIDIA cuSPARSE cusparseSgtsvInterleavedBatch 的接口语义,补齐 CANN Ascend 950 系列稀疏计算能力 改动方法: - 新增对外接口 aclsparseSgtsvInterleavedBatch(主接口)与 aclsparseSgtsvInterleavedBatch_bufferSizeExt(workspace 查询),定义于 include/cann_ops_sparse.h - 基于 SIMT 模型实现 kernel(src/gtsv_interleaved_batch/arch35/):每 block 64 线程,每线程独立处理 1 个 batch;线程局部状态保持在寄存器中,跨行依赖不经过 workspace GM 读写 - 采用 Thomas 算法(algo=0),workspace 仅存 d'[i] 供 backward 阶段使用,b'[i] 原位覆写到 x - 重构测试框架(新增 test/frame/ 公共组件:csv_loader、test_common、test_main),适配 CSV 数据驱动的算子测试 - 新增完整算子文档 src/gtsv_interleaved_batch/README.md ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> - #88 ## 测试 <!--描述进行了哪些测试来验证你的改动。--> - 新增 test/gtsv_interleaved_batch/ 测试用例,基于 CSV 数据驱动(gtsv_interleaved_batch_test.csv),覆盖 m=1 / 多 batch / 边界值等场景 - 提供 golden 参考实现(gtsv_interleaved_batch_golden.h)对比 NPU 计算结果 - 在 Ascend 950 上验证正确性(详见 README 预期输出样例)  ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> - 新增 src/gtsv_interleaved_batch/README.md:包含算子概述、接口函数原型、参数说明、约束条件、调用示例及预期输出 - 更新 include/cann_ops_sparse.h:新增 aclsparseSgtsvInterleavedBatch 与 _bufferSizeExt 接口声明及 Doxygen 注释 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!46 | 1 个月前 | |
feat(prune): 新增 aclsparseLtSpMMAPrune 2:4 结构化稀疏剪枝算子 Co-authored-by: wang-zhiyue2<wangzhiyue2@huawei.com> # message auto-generated for no-merge-commit merge: !117 merge feat/prune-standalone into master feat(prune): 新增 aclsparseLtSpMMAPrune 2:4 结构化稀疏剪枝算子 Created-by: wang-zhiyue2 Commit-by: wang-zhiyue2 Merged-by: cann-robot Description: ## 描述 新增 aclsparseLtSpMMAPrune 算子,对标 NVIDIA cuSPARSELt 的 cusparseLtSpMMAPrune,对稠密矩阵执行 2:4 结构化稀疏剪枝,输出与输入同型的稠密存储矩阵(被置零元素以 0 表示)。该算子是结构化稀疏矩阵乘法的前置步骤。 **核心特性:** - 剪枝对象由 Matmul 描述符中 matA/matB 的 sparsity 字段决定:matA 为 ACL_SPARSE_LT_SPARSITY_50_PERCENT 时剪枝矩阵 A(A-sparse),matB 为 ACL_SPARSE_LT_SPARSITY_50_PERCENT 时剪枝矩阵 B(B-sparse) - 支持两种剪枝算法:STRIP(逐分组剪枝)与 TILE(逐 tile 剪枝,4x4 tile 内行/列联合约束,90 种有效配置) - 支持 4 种数据类型:FP32 / FP16 / BF16 / INT8 - 支持转置路径:transA/transB 通过切换剪枝方向实现,转置写回已向量化(TransDataTo5HD) - 目标平台:Ascend 950PR / 950DT(arch35 / DAV_3510) **新增文件:** - sparseLt/prune/arch35/prune_host.cpp:Host 侧 Tiling 计算 + kernel launch(tiling by value,异步执行,无额外 device 存储) - sparseLt/prune/arch35/prune_kernel.cpp:Kernel 侧实现,STRIP/TILE 双算法 dispatch,沿行向量化(Cast+Abs+Mul keepMask)+ 沿列标量回退 - sparseLt/prune/arch35/prune_kernel.h:Kernel launcher 声明 - sparseLt/prune/README.md:算子文档 - sparseLt/shared/aclsparselt_internal.h:裁剪版共享内部头(TilingData 结构 + md_* helper + 常量宏) - sparseLt/shared/aclsparselt_host.cpp:共享平台查询函数(get_cube_core_num / get_ub_size) - test/prune/:完整测试工程(golden / param / npu_wrapper / test.cpp / csv) **接口签名:** c aclsparseStatus_t aclsparseLtSpMMAPrune( aclsparseLtConstHandle_t handle, aclsparseLtConstMatmulDescriptor_t* matmulDescr, const void* d_in, void* d_out, aclsparseLtPruneAlg_t pruneAlg, aclrtStream stream); ## 关联的Issue ## 测试 - GTest + CSV 驱动的精度 ST,覆盖 L0/L1/L2 分级 - prune 算子共 65 个测试用例:57 功能精度 + 7 异常路径 + 1 结构属性验证 - 覆盖 4 dtype × STRIP/TILE × 转置 × A-sparse/B-sparse × k奇数 × 非对齐shape - CPU golden 参考实现独立于 kernel(SpMMAPruneGolden) - 全量回归通过(ascend950)  ## 文档更新 - 新增 sparseLt/prune/README.md:算子使用文档 - 更新 docs/zh/api_list.md:追加 prune API 接口文档 - 更新 include/cann_ops_sparseLt.h:追加 SpMMAPrune 声明 + Const 类型定义 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!117 | 18 天前 | |
feat: add aclsparseScatter operator for Ascend910B (arch22) Co-authored-by: sushaGo<15991853807@163.com> # message auto-generated for no-merge-commit merge: !59 merge feat/scatter-operator into master feat: add aclsparseScatter operator for Ascend910B (arch22) Created-by: sushaGo Commit-by: sushaGo Merged-by: cann-robot Description: ## 描述 为 Ascend 910B(arch22)新增 aclsparseScatter 算子实现,支持将稀疏向量的非零元素按索引散布到稠密向量,执行 y[indices[i]] = values[i]。 改动原因: - ops-sparse 库此前缺少稀疏向量散布(scatter)算子,无法覆盖稀疏更新、embedding 梯度散布、图算法等场景中频繁出现的稀疏向量到稠密向量散布需求 - 需对齐 NVIDIA cuSPARSE cusparseScatter 的接口语义,补齐 CANN Ascend 910B(Atlas A2 训练/推理、A3 训练)系列稀疏计算能力 改动方法: - 新增对外接口 aclsparseScatter,定义于 include/cann_ops_sparse.h - 基于多核 Vector 并发模型实现 kernel(sparse/scatter/arch22/):host 按 coreNnzCount/coreNnzOffset 将 nnz 切分到各核,每核独立处理自身分片;kernel 入口 blockIdx 守卫提前返回,run-length 合并检测将连续索引段聚合为一次批量 DataCopyPad 写出,孤立点逐元素写,配 DoubleBuffer 流水;indices 先 Cast int64→int32 用于寻址 - host 侧 aclsparseScatter 数据全程驻留 Device,无 D2H 往返,仅 Tiling 数据 H2D 拷贝;nnz==0 早退 - 参照 spmv 测试结构重写 scatter 测试(test/scatter/arch22/scatter_test.cpp),采用模板化单用例 + 内联 CPU golden + bit-exact Verification + TestStats/RunAndTrack/RunRandomParams 骨架 - 新增完整算子文档 sparse/scatter/README.md ## 关联的Issue 关联Issue #101 ## 测试 - 新增 test/scatter/ 测试用例,覆盖 contiguous / reverse / stride / random-unique 四种互异索引分布,以及特殊值(0/-0/负数/大值/Inf/NaN)、非对齐 nnz、随机参数采样、1M 大规模等场景,共 56 例 - 提供 CPU 参考实现(ScatterCpu)对比 NPU 计算结果,按非计算类算子标准做逐位一致(bit-exact)判定 - 在 Ascend 910B 上验证正确性,56 例全部通过(通过率 100%)  ## 文档更新 - 新增 sparse/scatter/README.md:包含算子概述(含 vecX 分离存储格式说明)、接口函数原型、参数说明、支持的数据类型、约束条件(含「索引去重有序」确定性约束、索引范围)、调用示例 - 更新 include/cann_ops_sparse.h:新增 aclsparseScatter 接口声明 ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!59 | 1 个月前 | |
feat(sddmm): implement SDDMM sampled dense-dense matrix multiplication operator Co-authored-by: wang-zhiyue2<wangzhiyue2@huawei.com> # message auto-generated for no-merge-commit merge: !82 merge feat/sddmm into master feat(sddmm): implement SDDMM sampled dense-dense matrix multiplication operator Created-by: wang-zhiyue2 Commit-by: wang-zhiyue2 Merged-by: cann-robot Description: ## 描述 实现 SDDMM(Sampled Dense-Dense Matrix Multiplication,采样稠密-稠密矩阵乘法)算子,计算 C_out = (alpha * X * Y^T + beta * C) ∘ spy(C),只在稀疏矩阵 C 的非零位置上计算 X 与 Y 的点积,结果原地写回 C 的 values 数组。 **核心特性:** - 三阶段执行模型:BufferSize → Preprocess → Execute,对标 cuSPARSE cusparseSDDMM Generic API - 行重排 + 贪心分箱(Greedy Row Bin Packing)实现核间负载均衡 - K 维分块(K-Tiling)+ 双缓冲 X/Y,重叠 MTE2 搬运与 V 计算 - Strided GM→UB 优化:非连续访问使用 DataCopyPad strided + Gather 紧凑化 - Pattern cache:相同 CSR pattern 跳过 rebuild 仅刷新标量,加速重复调用 - 支持 opX/opY 的 NON_TRANSPOSE / TRANSPOSE - 支持 X/Y 的 ROW-major / COL-major 内存布局(RR/RC/CR/CC) - 支持 FP32(FP32 累加)和 FP16(FP32 累加 + 饱和截断)两种数据类型 - 目标平台:Ascend 950PR / 950DT(arch35 / DAV-3510) **新增接口:** - aclsparseSDDMMBufferSize:查询 workspace 大小 - aclsparseSDDMMPreprocess:预处理(行重排 + 贪心分箱),加速重复调用 - aclsparseSDDMM:执行采样矩阵乘法,结果原地更新 C 的 values 数组 ## 关联的Issue #122 ## 测试 - GTest + CSV 驱动的精度 ST,覆盖 L0(基础功能)/ L1(参数组合)/ L2(边界场景)/ WB(白盒)/ CM(col-major)/ TX(transpose) - CPU golden 参考实现(FP64 累加,逐非零元素点积) - 覆盖 FP32/FP16 × NON_TRANSPOSE/TRANSPOSE × ROW-major/COL-major 组合 - 非对齐尺寸(519/775/693 等)、极稀疏(ratio=0.1)、空 tensor(nnz=0)边界测试 - FP16 饱和截断验证(大值域 ±50) - 10 个异常用例 + 75 个精度用例,共 85/85 全部通过  ## 文档更新 - 新增 sparse/sddmm/README.md:完整算子文档,包含接口说明、参数约束、调用示例、算法说明 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!82 | 1 个月前 | |
feat(sparse2dense): 新增 SparseToDense 算子 Co-authored-by: yangzhenya<yangzhenya4@huawei.com> # message auto-generated for no-merge-commit merge: !100 merge feat/sparse2dense into master feat(sparse2dense): 新增 SparseToDense 算子 Created-by: m0_72281197 Commit-by: yangzhenya Merged-by: cann-robot Description: # aclsparseSparseToDense 算子 > 本文面向 ops-sparse 接口使用者。 ## 功能描述 SparseToDense 将 CSR、CSC 或 COO 格式的稀疏矩阵转换为稠密矩阵。接口语义对标 cuSPARSE Generic API 的 cusparseSparseToDense_bufferSize 和 cusparseSparseToDense。推荐按查询 workspace、执行转换两个阶段调用。 计算如下表达式: $$ B_{ij} = \begin{cases} A_{ij} & \text{若 } (i,j) \in \text{nnz}(A) \\ 0 & \text{否则} \end{cases} $$ 其中: - $A$ 是 $m \times n$ 的稀疏矩阵(CSR / CSC / COO 格式) - $B$ 是 $m \times n$ 的稠密矩阵(输出,行主序或列主序) 主要特性: - **纯数据搬运**:kernel 仅执行 B[idx] = A.val[p] 的 scatter 写操作,无任何算术运算、无类型转换,输入输出同 dtype,故**零精度损失**(bit-exact) - **三格式支持**:CSR、CSC、COO 三种稀疏格式,通过描述符 format 字段自动分流 - **多核并行**:CSR/CSC 按行/列切分到多个 AI Core,COO 按 nnz grid-stride 切分;SIMT 线程并行 scatter - **全 dtype 输出同型**:直接以原始 dtype 读写,不做 float 中转 - **支持异步执行**:两个 API 均异步返回,同步由调用方通过 stream 负责 - **零 workspace**:scatter 写无需临时缓冲,bufferSize 恒返回 0 - **支持行/列主序输出**:通过 aclsparseOrder_t 指定,支持任意 leading dimension(ld) ## 接口原型 cpp aclsparseStatus_t aclsparseSparseToDense_bufferSize( aclsparseHandle_t handle, aclsparseConstSpMatDescr_t matA, aclsparseDnMatDescr_t matB, aclsparseSparseToDenseAlg_t alg, size_t *bufferSize); aclsparseStatus_t aclsparseSparseToDense( aclsparseHandle_t handle, aclsparseConstSpMatDescr_t matA, aclsparseDnMatDescr_t matB, aclsparseSparseToDenseAlg_t alg, void *buffer); matA 是只读稀疏矩阵描述符,matB 是可变稠密矩阵描述符。接口不会修改 matA 或其数据。 ## 参数说明 两个接口的公共参数如下。 | 参数 | 内存位置 | 方向 | 类型 | 说明 | |------|----------|------|------|------| | handle | Host | 输入 | aclsparseHandle_t | ops-sparse 上下文句柄,携带执行 stream,不可为空 | | matA | Host 描述符;数据在 Device | 输入 | aclsparseConstSpMatDescr_t | 稀疏矩阵 A,包含格式、行列数、索引类型、indexBase、值类型和数据指针 | | matB | Host 描述符;数据在 Device | 输入/输出 | aclsparseDnMatDescr_t | 稠密矩阵 B,包含行数、列数、ld、布局、数据类型和数据指针;执行时写入 | | alg | Host | 输入 | aclsparseSparseToDenseAlg_t | 仅支持 ACL_SPARSE_SPARSETODENSE_ALG_DEFAULT | 各接口的专有参数如下。 | 接口 | 参数 | 内存位置 | 方向 | 说明 | |------|------|----------|------|------| | bufferSize | bufferSize | Host | 输出 | workspace 字节数,不可为空;当前恒返回 0 | | execute | buffer | Device | 输入 | workspace;bufferSize == 0 时可为空 | ## 推荐调用流程 1. 创建 handle、稀疏矩阵描述符 matA 和稠密矩阵描述符 matB。 2. 调用 aclsparseSparseToDense_bufferSize,按返回大小分配 Device workspace(当前恒为 0,可跳过)。 3. 调用 aclsparseSparseToDense 执行转换。 4. 同步 handle 绑定的 stream,读取结果。 ## 稀疏格式语义 | 格式 | matA 描述符字段 | 说明 | |------|-------------------|------| | CSR | ptrs=rowOffsets(m+1), idxs=colInd(nnz) | 按行压缩;kernel 按行切分多核 | | CSC | ptrs=colOffsets(n+1), idxs=rowInd(nnz) | 按列压缩;kernel 按列切分多核 | | COO | ptrs=cooRowInd(nnz), idxs=cooColInd(nnz) | 坐标格式;kernel 按 nnz grid-stride 切分 | CSR/CSC 的 ptrType 与 IdxType 必须均为 ACL_SPARSE_INDEX_32I。COO 的 cooIdxType 必须为 ACL_SPARSE_INDEX_32I。所有格式均支持 ACL_SPARSE_INDEX_BASE_ZERO 和 ACL_SPARSE_INDEX_BASE_ONE。 COO 格式中重复的 (row, col) 遵循 last-write-wins 语义(与 cuSPARSE 一致)。 ## 支持数据类型 arch35 实现支持以下 value 类型,且 matA 与 matB 的 value 类型必须相同。 | 数据类型 | 枚举 | 元素大小 | |----------|------|---------| | float32 | ACL_FLOAT | 4B | | float16 | ACL_FLOAT16 | 2B | | bfloat16 | ACL_BF16 | 2B | | int32 | ACL_INT32 | 4B | | int8 | ACL_INT8 | 1B | 不支持 float64 和任何复数类型;传入这些类型返回 ACL_SPARSE_STATUS_NOT_SUPPORTED。 ## 数值、布局与边界语义 - 同时支持 ACL_SPARSE_ORDER_ROW(row-major)和 ACL_SPARSE_ORDER_COL(column-major)。 row-major 要求 ld >= n,column-major 要求 ld >= m。 - leading dimension (ld) 可大于最小值(即允许 stride padding),用于满足对齐需求。 - matA 和 matB 的 value 类型必须一致,不支持跨类型转换。kernel 以原始 dtype 读写, 保证 bit-exact 无精度损失。 - matB 的 Device 内存由算子内部通过 aclrtMemset 清零,调用方无需预先清零。 - NaN(包括其 payload)、+Inf、-Inf、+0、-0 和普通有限非零值均按位搬运, 不执行数值计算或类型转换。 - 支持零维矩阵、全零矩阵和全非零矩阵。nnz=0 时仅执行清零后直接返回,不 launch kernel。 - 矩阵行数、列数不可超过 INT32_MAX。 ## Workspace 与生命周期 - workspace 是每次调用使用的临时 scratch,不保存跨调用状态。bufferSize 恒返回 0, buffer 可传 nullptr。 - 执行按 handle 的 stream 异步执行,调用者必须在读取或释放输出、描述符及 handle 前同步该 stream。 - 描述符只借用 Device 指针,不拥有其内存。先同步 stream,再销毁描述符并释放其引用的 Device 内存。 ## 返回值 / 错误码 | 返回值 | 含义 | |--------|------| | ACL_SPARSE_STATUS_SUCCESS | 成功 | | ACL_SPARSE_STATUS_HANDLE_IS_NULLPTR | handle 为 NULL | | ACL_SPARSE_STATUS_INVALID_VALUE | matA/matB 为 NULL;bufferSize 为 NULL;stream 未设置;维度不匹配;matB.values 为 NULL;nnz>0 但 idxs/values 为 NULL | | ACL_SPARSE_STATUS_NOT_SUPPORTED | 格式非 CSR/CSC/COO;索引类型非 I32;值类型不在支持列表;matA/matB 值类型不一致;alg 非 DEFAULT;m/n 超过 INT32_MAX | ## 调用示例 cpp #include <stdio.h> #include <stdlib.h> #include "cann_ops_sparse.h" #include "acl/acl.h" #define CHECK_STATUS(call) \ do { \ aclsparseStatus_t _st = (call); \ if (_st != ACL_SPARSE_STATUS_SUCCESS) { \ fprintf(stderr, "ERROR: %s failed at line %d, status=%d\n", \ #call, __LINE__, static_cast<int>(_st)); \ exit(EXIT_FAILURE); \ } \ } while (0) #define CHECK_ACL_RT(call) \ do { \ aclError _st = (call); \ if (_st != ACL_SUCCESS) { \ fprintf(stderr, "ERROR: %s failed at line %d, status=%d\n", \ #call, __LINE__, static_cast<int>(_st)); \ exit(EXIT_FAILURE); \ } \ } while (0) int main() { // 1. 初始化 ACL 环境 CHECK_ACL_RT(aclInit(nullptr)); CHECK_ACL_RT(aclrtSetDevice(0)); aclrtStream stream = nullptr; CHECK_ACL_RT(aclrtCreateStream(&stream)); // 2. CSR 矩阵数据(4x4,nnz=5,0-based) // [1.0 0 2.0 0 ] // [0 3.0 0 0 ] // [4.0 0 5.0 0 ] // [0 0 0 0 ] int32_t hRowOff[] = {0, 2, 3, 5, 5}; int32_t hColInd[] = {0, 2, 1, 0, 2}; float hValues[] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f}; int64_t rows = 4, cols = 4, nnz = 5; // 3. 分配 Device 内存并拷贝 CSR 数据 int32_t *dRowOff = nullptr, *dColInd = nullptr; float *dValues = nullptr, *dDnMat = nullptr; CHECK_ACL_RT(aclrtMalloc((void **)&dRowOff, sizeof(hRowOff), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL_RT(aclrtMalloc((void **)&dColInd, sizeof(hColInd), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL_RT(aclrtMalloc((void **)&dValues, sizeof(hValues), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL_RT(aclrtMalloc((void **)&dDnMat, rows * cols * sizeof(float), ACL_MEM_MALLOC_HUGE_FIRST)); CHECK_ACL_RT(aclrtMemcpy(dRowOff, sizeof(hRowOff), hRowOff, sizeof(hRowOff), ACL_MEMCPY_HOST_TO_DEVICE)); CHECK_ACL_RT(aclrtMemcpy(dColInd, sizeof(hColInd), hColInd, sizeof(hColInd), ACL_MEMCPY_HOST_TO_DEVICE)); CHECK_ACL_RT(aclrtMemcpy(dValues, sizeof(hValues), hValues, sizeof(hValues), ACL_MEMCPY_HOST_TO_DEVICE)); // 4. 创建 handle aclsparseHandle_t handle = nullptr; CHECK_STATUS(aclsparseCreate(&handle)); CHECK_STATUS(aclsparseSetStream(handle, stream)); // 5. 创建 CSR 稀疏矩阵描述符 matA aclsparseConstSpMatDescr_t matA = nullptr; CHECK_STATUS(aclsparseCreateConstCsr(&matA, rows, cols, nnz, dRowOff, dColInd, dValues, ACL_SPARSE_INDEX_32I, ACL_SPARSE_INDEX_32I, ACL_SPARSE_INDEX_BASE_ZERO, ACL_FLOAT)); // 6. 创建稠密矩阵描述符 matB(行主序,ld=cols) aclsparseDnMatDescr_t matB = nullptr; CHECK_STATUS(aclsparseCreateDnMat(&matB, rows, cols, cols, dDnMat, ACL_FLOAT, ACL_SPARSE_ORDER_ROW)); // 7. 查询 workspace(恒为 0) size_t bufferSize = 0; CHECK_STATUS(aclsparseSparseToDense_bufferSize(handle, matA, matB, ACL_SPARSE_SPARSETODENSE_ALG_DEFAULT, &bufferSize)); // 8. 执行 CSR → Dense 转换 CHECK_STATUS(aclsparseSparseToDense(handle, matA, matB, ACL_SPARSE_SPARSETODENSE_ALG_DEFAULT, nullptr)); // 9. 同步并取回结果 CHECK_ACL_RT(aclrtSynchronizeStream(stream)); float hDnMat[16] = {0}; CHECK_ACL_RT(aclrtMemcpy(hDnMat, sizeof(hDnMat), dDnMat, sizeof(hDnMat), ACL_MEMCPY_DEVICE_TO_HOST)); // 10. 打印结果 printf("Dense matrix (%lld x %lld, row-major):\n", (long long)rows, (long long)cols); for (int64_t i = 0; i < rows; ++i) { for (int64_t j = 0; j < cols; ++j) { printf("%6.1f ", hDnMat[i * cols + j]); } printf("\n"); } // 11. 清理 aclsparseDestroyDnMat(matB); aclsparseDestroySpMat(matA); aclsparseDestroy(handle); aclrtFree(dDnMat); aclrtFree(dValues); aclrtFree(dColInd); aclrtFree(dRowOff); aclrtDestroyStream(stream); aclrtResetDevice(0); aclFinalize(); return 0; } 预期输出: Dense matrix (4 x 4, row-major): 1.0 0.0 2.0 0.0 0.0 3.0 0.0 0.0 4.0 0.0 5.0 0.0 0.0 0.0 0.0 0.0 ## 测试覆盖 测试文件位于 test/sparse2dense/,采用 GTest + CSV 参数化测试框架,共 **50 个测试用例**(32 正确性 + 16 负向 + 2 跳过),在 Ascend950 真机全部通过。 ### 测试结构 | 文件 | 说明 | |------|------| | sparse2dense_param.h | CSV 参数结构体 | | sparse2dense_golden.h | CPU golden 计算(CSR/CSC/COO 三格式) | | arch35/sparse2dense_test.csv | L0/L1 正确性用例(32 条) | | arch35/sparse2dense_l2_cases.csv | L2 负向用例(16 条) | | arch35/sparse2dense_npu_wrapper.h | NPU 输入生成 / 类型映射 / 执行封装 | | arch35/sparse2dense_test.cpp | GTest 主测试 | ### L0/L1 正确性测试(32 条) | 级别 | 覆盖维度 | |------|----------| | L0 | 基本功能:CSR/CSC/COO × FP32/FP16/BF16/INT8/INT32 × row/col × base 0/1 | | L0 | 边界:空矩阵 / 单元素 / 全密 / ld padding / 宽矩阵 / 高矩阵 | | L1 | 中等规模:128×128 ~ 512×512 × 三格式 × 五 dtype | | L1 | indexBase=1 覆盖 | | L1 | 三格式一致性(同矩阵 CSR/CSC/COO 输出必须一致) | ### L2 负向测试(16 条) | 测试类别 | 覆盖内容 | |----------|----------| | 空指针 | handle / matA / matB / bufferSize 为 NULL | See merge request: cann/ops-sparse!100 | 1 个月前 | |
feat: 新增 aclsparseLtMatmulDescriptorInit 接口及 aclsparseLt 描述符类型体系 Co-authored-by: zhengyifei<yiwaiii@mail.ustc.edu.cn> Co-authored-by: zhengyifei<ak4C9wY14UkwTcbk.zhengyifei@noreply.gitcode.com> # message auto-generated for no-merge-commit merge: !76 merge feat/aclsparseLt-matmul-descriptor-init into master feat: 新增 aclsparseLtMatmulDescriptorInit 接口及 aclsparseLt 描述符类型体系 Created-by: zhengyifei Commit-by: zhengyifei Merged-by: cann-robot Description: ## 描述 搭建 aclsparseLt 描述符类型体系。本组接口为 Host 侧描述符初始化,不涉及 NPU kernel,arch 无关。 新增 5 个接口: aclsparseLtDenseDescriptorInit / aclsparseLtStructuredDescriptorInit(矩阵描述符初始化)、aclsparseLtMatmulDescriptorInit(主接口)、aclsparseLtMatDescriptorDestroy / aclsparseLtMatmulDescriptorDestroy(销毁)。 新增 4 个类型:aclsparseLtMatDescriptor_t / aclsparseLtMatmulDescriptor_t(opaque pointer)、aclsparseLtSparsity_t(2:4 结构化稀疏)、aclsparseComputeType_t(独立计算精度,与 aclDataType 解耦)。支持 7 种数据类型与 3 种计算精度。 采用 opaque pointer 模式隐藏实现,参数校验顺序为指针→handle→防覆盖→维度对齐→枚举→类型组合。SetAttribute/GetAttribute 本期不实现,batch/scale 仅预留字段。 ### 变更文件 | 类别 | 文件 | 说明 | |------|------|------| | **头文件** | include/cann_ops_sparseLt.h | 新增 4 类型 + 5 接口声明 | | **实现** | sparseLt/common/aclsparselt_mat_descriptor*.cpp/_internal.h | 矩阵描述符初始化/销毁 | | **实现** | sparseLt/common/aclsparselt_matmul_descriptor*.cpp/_internal.h | Matmul 描述符初始化/销毁 | | **文档** | sparseLt/common/README.md | 接口规格文档 | | **构建** | cmake/test.cmake | 新增 NO_SRC_DIR 选项 | | **测试** | test/sparseLt/matmulDescriptorInit/ | GTest + CSV 驱动测试 | | **目录文档** | docs/zh/install/dir_structure.md | 更新 sparseLt 目录树描述 | ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/113 ## 测试 | 项目 | 值 | |------|-----| | 总用例数 | 126 | | 通过 | 126 | | 失败 | 0 | ## 文档更新 - sparseLt/common/README.md:接口规格文档(接口原型、参数、约束、数据类型支持矩阵、调用示例、范围限制) - docs/zh/install/dir_structure.md:更新 sparseLt 目录树描述 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!76 | 23 天前 | |
feat(spmm): add arch22 spmm implementation and tests Co-authored-by: xssxyz<xssxyz@163.com> # message auto-generated for no-merge-commit merge: !92 merge master into master feat(spmm): add arch22 spmm implementation and tests Created-by: xssxyz Commit-by: xssxyz Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> spmm 算子 arch22 实现,包含测试代码 ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> ## 测试 <!--描述进行了哪些测试来验证你的改动。--> ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [ X] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!92 | 20 天前 | |
fix(spmv): 对齐生态精度标准的测试数据生成与混合容差校验 Co-authored-by: rueenov11<zhuruyi@huawei.com> # message auto-generated for no-merge-commit merge: !79 merge fix/spmv-test-value-range into master fix(spmv): 对齐生态精度标准的测试数据生成与混合容差校验 Created-by: rueenov11 Commit-by: rueenov11 Merged-by: cann-robot Description: ## 描述 本 PR 对 test/spmv/arch22/spmv_test.cpp 做了两处调整,使 SpMV ST 测试与[生态算子开源精度标准](https://gitcode.com/cann/opbase/blob/master/docs/zh/ops_precision_standard/experimental_standard.md)保持一致: ### 1. 测试数据生成:均匀分布值域调整为 [-5, 5] 将 CSR 非零元(GenerateCsr)、稠密向量 x/y(GenerateDenseVector)的均匀分布从 [-5, 10) 改为 [-5, 5),符合标准 1.2 节对均匀分布 case 的值域要求。 ### 2. 精度校验:由纯相对误差改为混合容差(Mixed Tolerance) 原实现使用纯相对误差(2^-13 阈值 + 任一元素超差即 fail),在 [-5, 5] 对称分布下 golden 值偏小、正负抵消增多,容易误报精度失败。 现改为标准规定的混合容差判定: - **逐元素**:|actual - golden| ≤ atol + rtol × |golden| - **整体通过**:matched_ratio ≥ 0.99 且 max_abs_error ≤ max_abs_error_limit 各输出类型阈值: | OutT | rtol | atol | max_abs_error_limit | |----------|--------|--------|---------------------| | float | 2^-10 | 2^-16 | 1e-2 | | half | 2^-9 | 2^-9 | 1e-1 | | bfloat16 | 2^-6 | 2^-6 | 1e-0 | | int32 | 精确匹配(100% 通过率) | | | 失败 case 日志字段同步更新为 max_abs_error 和 matched_ratio。 ## 关联的Issue https://gitcode.com/cann/ops-sparse/issues/92 ## 测试 - [x] 在 NPU 环境编译并运行 spmv_test 全量用例(205 cases) - [x] 验证 [-5, 5] 均匀分布下,原先因纯相对误差误报的 case 可通过混合容差校验 - [x] float / half / bfloat16 / int32 及 Transpose、混合精度路径均覆盖 ## 文档更新 无文档变更。 ## 类型标签 - [x] Bug修复 - [ ] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!79 | 1 个月前 | |
feat: 新增 aclsparseSpMVOp 算子接口(Ascend950/arch35) Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !66 merge aclsparseSpMVOp into master feat: 新增 aclsparseSpMVOp 算子接口(Ascend950/arch35) Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 描述 新增 aclsparseSpMVOp 算子接口,提供稀疏矩阵-向量乘法(带独立输出向量 + 可定制 epilogue)能力,对标 cuSPARSE cusparseSpMVOp() [EXPERIMENTAL]。 计算表达式:Z = epilogue(α * Σ op(A_ik) * X_k + β * Y_i),其中 A 为 m×k 的 CSR 稀疏矩阵,X/Y/Z 均为稠密向量,Z 可与 Y 别名实现 in-place;epilogue 在 NPU 侧固定为 identity。 本次新增 7 个 Generic API 函数(全部异步返回): - aclsparseSpMVOp_bufferSize:获取 workspace 字节数 - aclsparseSpMVOp_createDescr:创建描述符并执行预处理(ALG2 异步 launch preprocess kernel) - aclsparseSpMVOp_destroyDescr:销毁描述符(幂等) - aclsparseSpMVOp_createPlan:创建执行计划(identity epilogue) - aclsparseSpMVOp_destroyPlan:销毁执行计划(幂等) - aclsparseSpMVOp_setGlobalUserData:设置 epilogue 用户数据(NPU 侧 no-op) - aclsparseSpMVOp:主执行入口 ## 关联的Issue - #106 ## 测试 新增参数化 GTest 套件 (test/spmv_op/): - 覆盖 HOST/DEVICE pointerMode、ALG1/ALG2、未排序索引等组合  ## 文档更新 新增算子文档 sparse/spmv_op/README.md:包含算子概述、7 个 API 的函数原型/参数说明/约束说明、支持的稀疏格式与算法对比、完整调用示例。 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!66 | 1 个月前 | |
feat(spsm): implement SpSM sparse triangular solve with multiple right-hand sides Co-authored-by: wang-zhiyue2<wangzhiyue2@huawei.com> # message auto-generated for no-merge-commit merge: !84 merge aclsparseSpSM into master feat(spsm): implement SpSM sparse triangular solve with multiple right-hand sides Created-by: wang-zhiyue2 Commit-by: wang-zhiyue2 Merged-by: cann-robot Description: ## 描述 实现 SpSM(Sparse Triangular Solve with Multiple Right-Hand Sides)算子,用于求解稀疏三角线性方程组 op(A)·X = α·B。 **核心特性:** - 三阶段执行模型:BufferSize → Analysis → Solve,对标 cuSPARSE cusparseSpSM Generic API - Descriptor 描述符模式,Analysis 阶段 host 侧 CSR→CSC 转置 + CPU Level Scheduling 拓扑分层,Solve 阶段异步执行 - Level Scheduling 并行化算法,同 level 行无依赖可多核并行,level 间串行求解 - 支持 NON_TRANSPOSE / TRANSPOSE 操作(opA=T 时 host 侧物理转置为 CSC 再按 N 模式处理) - 支持 LOWER / UPPER fill mode 和 UNIT / NON_UNIT diagonal type - 支持 ROW / COL 矩阵存储顺序,支持 in-place 求解(B/X 共用缓冲区) - 支持 32-bit 索引,支持 ONE_BASED / ZERO_BASED 索引基 - 接口签名对齐 cuSPARSE(含 opB 参数),首期仅实现 opB=NON_TRANSPOSE - 目标平台:Ascend 950PR / 950DT(arch35 / DAV_3510) **新增接口:** - aclsparseSpSMCreateDescr / aclsparseSpSMDestroyDescr:SpSM 描述符生命周期管理 - aclsparseSpSMBufferSize:查询 workspace 大小 - aclsparseSpSMAnalysis:预处理(CSR→CSC 转置 + Level Scheduling) - aclsparseSpSM:执行三角求解 ## 关联的Issue #126 ## 测试 - GTest + CSV 驱动的精度 ST,94 条参数化用例 + 20 条异常用例,共 114 条 - 分级覆盖:L0(基础功能 8 条)/ L1(参数组合 58 条)/ L2(边界场景 12 条)/ L3(白盒路径 + 回归 16 条) - CPU golden 参考实现(Eigen FP64 triangularView 求解),覆盖 opA N/T × fillMode L/U × diag UNIT/NON_UNIT 全 8 种模式 - 覆盖 ROW/COL order × in-place × unsorted × 不同 alpha × 不同 density × 奇异矩阵 × 空矩阵等场景 - 异常用例覆盖 null 指针 / 类型不支持 / 维度不匹配 / 奇异矩阵等校验路径 - 精度标准:MIXED_TOLERANCE,114/114 pass  ## 文档更新 - 新增 sparse/spsm/README.md:完整算子文档,包含功能说明、数学原理(行更新通式、四种依赖模式、Level Scheduling)、接口说明、参数约束、调用示例 ## 类型标签 - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [x] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!84 | 1 个月前 | |
feat(spsv): support int64 index type for large sparse matrices in spsv Co-authored-by: justsheldon<taoxudong@huawei.com> # message auto-generated for no-merge-commit merge: !93 merge feature/spsv-int64-support into master feat(spsv): support int64 index type for large sparse matrices in spsv Created-by: justsheldon Commit-by: justsheldon Merged-by: cann-robot Description: ## 概要 为 SpSV 算子扩展索引类型支持,对标 cuSPARSE cusparseSpSV 的完整语义能力。本 PR 包含三项增强: 1. **大规模矩阵支持**:nnz > INT32_MAX 的 I64 索引稀疏矩阵求解(workspace 升级 + 条件串行化) 2. **Fortran 兼容**:支持 ACL_SPARSE_INDEX_BASE_ONE(1-based 索引) 3. **混合索引宽度**:支持 (I64 rowPtr, I32 colInd) 组合(节省大型矩阵内存) 同步清理了 README 与 public header 中与实际实现不符的注释。 ## 设计思路 ### 1. 大规模矩阵:选择性升级 + 条件串行化 详细设计见 .cannbot/spsv/spsv-int64-design.md: - **Workspace 按 permType 分配元素宽度**:nnz > INT32_MAX 时 perm/transPerm/diagPtr 使用 int64,其余 m-scaled 数组保持 int32 - **Kernel 模板参数化 <RowPtrT, ColIndT, PermT>**:format conversion / analysis / solve 函数按三元组分发 - **nnz > INT32_MAX 强制串行格式转换**:规避 arch35 上 asc_atomic_add 的 int64 不确定性 - **int32 路径零退化**:nnz <= INT32_MAX 时完全走现有 int32 路径 ### 2. INDEX_BASE_ONE:kernel 内转换 采用 kernel format conversion 路径内处理 1-based 转换(不改动 solve kernel 核心逻辑): - ValidateSpSVIndexTypes 放行 ACL_SPARSE_INDEX_BASE_ONE - cachedIdxBase 缓存在 descriptor,SpsvTilingData.idxBase 透传到 kernel - Host ComputeWorkspaceOffsets 为 1-based CSR 额外分配 workspace CSR 数组 - Kernel 内 format conversion 函数读取索引时减去 idxBase,构建 0-based 副本 - SpsvResolveEffectivePtrs 对 1-based CSR 重定向到 0-based workspace 副本 - solve kernel 无需修改 ### 3. 混合索引宽度:双模板 <RowPtrT, ColIndT> 将 kernel 从单模板 <IdxT> 扩展为双模板 <RowPtrT, ColIndT>: - RowPtrT:行偏移数组类型(CSR rowOffsets / CSC colOffsets / SELL sliceOffsets) - ColIndT:列索引数组类型(CSR colIndices / CSC rowIndices / COO 双索引) - Workspace 大小按 rowPtrSize 和 colIndSize 分别计算 ## 测试 **157/157 PASS**(原有 141 + 新增 16) ### 新增测试分布 | 类别 | 数量 | 说明 | |------|:----:|:-----| | I64 基本功能 | 4 | CSR/CSC/COO/SLICED_ELL + I64 | | I32/I64 交叉验证 | 4 | 验证 bit-exact 等价性 | | permType=1 强制路径 | 3 | CSR/COO/CSR_TRANSPOSE | | INDEX_BASE_ONE | 5 | CSR/CSC/COO + lower/upper/transpose/I64 |  ## 文档与注释修复 - README.md: - 索引类型约束改为四行表格,明确支持的索引组合矩阵 - INDEX_BASE 约束更新为 ZERO/ONE 均支持 - nnz > INT32_MAX 前提条件明确化(必须 I64 rowPtr) - Workspace 章节补全 1-based 归一化说明 - SpSVDescr 缓存字段列表补全 - cann_ops_sparse.h: - ACL_SPARSE_INDEX_64I 枚举注释按算子分情况说明(SpSV 全支持,SpMV/SpMM 暂未支持) ## 目标平台 Ascend 950 / DAV_3510 (arch35) only --- ## 关联的 Issue #125 (https://gitcode.com/cann/ops-sparse/issues/125) See merge request: cann/ops-sparse!93 | 1 个月前 | |
新增spvv算子和测试代码 Co-authored-by: 李恒琼<870124465@qq.com> # message auto-generated for no-merge-commit merge: !53 merge master into master 新增spvv算子和测试代码 Created-by: bjisdbvjhbsdvk Commit-by: 李恒琼 Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> ## 关联的Issue <!-- 如果这个PR是为了解决特定的Issue,请在这里提供Issue链接。例如:关联Issue #000--> https://gitcode.com/cann/ops-sparse/issues/100 ## 测试 <!--描述进行了哪些测试来验证你的改动。-->   ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 其他,请描述: See merge request: cann/ops-sparse!53 | 30 天前 | |
fix: build.sh --run 将不支持当前架构的算子标记为 skipped 而非 failed (#93) Co-authored-by: zhanghua145<zhanghua25@mails.ucas.ac.cn> # message auto-generated for no-merge-commit merge: !56 merge fix/skip-unsupported-ops into master fix: build.sh --run 将不支持当前架构的算子标记为 skipped 而非 failed (#93) Created-by: zhanghua145 Commit-by: zhanghua145 Merged-by: cann-robot Description: ## 修复内容 修复 #93 :build.sh --run 在测试二进制不存在时,将不支持当前架构的算子标记为 failed 而非 skipped,导致测试汇总误报失败。 ### 原因分析 - spmv 仅在 src/spmv/arch22/ 下有实现,ascend950(arch35)无对应源码 - CMake 构建阶段已正确跳过 spmv,但 build.sh 的 --run 逻辑在发现测试二进制不存在时直接判定为 failed ### 修复方案(参考 ops-blas 仓的 skip 机制) 1. cmake/test.cmake:跳过算子时写入 skipped_tests.list 2. test/CMakeLists.txt:初始化 skipped_tests.list 3. build.sh:读取 skip 清单,新增 SKIPPED_OPS 和 print_skip,汇总新增 Skipped 行 ### 验证结果 bash build.sh --run --soc=ascend950 Test Summary: Passed: 4 - csrgeam2 gtsv_interleaved_batch nnz spmm Skipped: 1 - spmv (not supported on ascend950) Failed: 0 See merge request: cann/ops-sparse!56 | 1 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 20 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 23 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 18 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 23 天前 | ||
| 20 天前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 1 个月前 | ||
| 30 天前 | ||
| 1 个月前 |