Csrgeam2算子【免费下载链接】ops-sparse本项目是CANN提供的高性能稀疏矩阵计算的算子库专注于优化稀疏矩阵的计算效率。项目地址: https://gitcode.com/cann/ops-sparse算子概述csrgeam2 算子用于计算两个 CSRCompressed Sparse Row格式稀疏矩阵的线性组合C α * A β * B其中 A、B、C 均为 m × n 稀疏矩阵以 CSR 格式存储α 和 β 为 FP32 标量。csrgeam2 采用两步法Nnz 阶段计算输出矩阵 C 的行指针csrRowPtrC和非零元素总数nnzCCompute 阶段根据 C 的行指针计算列索引csrColIndC和非零元素值csrValCC 的非零模式为 A 和 B 的并集A ∪ B与 α、β 的具体数值无关。仅支持非转置No-Transpose模式不支持 NT/TN/TT 组合。包含以下接口接口名功能简述aclsparseScsrgeam2_bufferSizeExt查询 workspace 大小字节aclsparseXcsrgeam2Nnz计算 C 的行指针 csrRowPtrC 和非零元素总数 nnzCaclsparseScsrgeam2执行 C α * A β * B计算列索引和非零元素值算子执行接口aclsparseScsrgeam2_bufferSizeExt产品支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持函数原型aclsparseStatus_t aclsparseScsrgeam2_bufferSizeExt( aclsparseHandle_t handle, int m, int n, const float *alpha, const aclsparseMatDescr_t descrA, int nnzA, const float *csrSortedValA, const int *csrSortedRowPtrA, const int *csrSortedColIndA, const float *beta, const aclsparseMatDescr_t descrB, int nnzB, const float *csrSortedValB, const int *csrSortedRowPtrB, const int *csrSortedColIndB, const aclsparseMatDescr_t descrC, const float *csrSortedValC, const int *csrSortedRowPtrC, const int *csrSortedColIndC, size_t *pBufferSizeInBytes);参数说明参数名输入/输出参数类型说明handle输入aclsparseHandle_tops-sparse 库上下文句柄携带 stream、pointerMode 等信息Host 内存m输入int矩阵 A、B、C 的行数m 0Host 内存n输入int矩阵 A、B、C 的列数n 0Host 内存alpha输入const float*标量 α 指针用于 A 的乘法系数。内存位置由aclsparseSetPointerMode控制Host/Device 内存descrA输入const aclsparseMatDescr_t矩阵 A 的描述符仅支持ACL_SPARSE_MATRIX_TYPE_GENERAL类型Host 内存nnzA输入int矩阵 A 的非零元素个数nnzA 0Host 内存csrSortedValA输入const float*A 的非零元素值数组长度为 nnzAnnzA0 时可为 nullptr本函数不读取Device 内存csrSortedRowPtrA输入const int*A 的行指针数组长度为 m1m0 时可为 nullptrDevice 内存csrSortedColIndA输入const int*A 的列索引数组长度为 nnzAnnzA0 时可为 nullptrDevice 内存beta输入const float*标量 β 指针用于 B 的乘法系数。内存位置由aclsparseSetPointerMode控制Host/Device 内存descrB输入const aclsparseMatDescr_t矩阵 B 的描述符仅支持ACL_SPARSE_MATRIX_TYPE_GENERAL类型Host 内存nnzB输入int矩阵 B 的非零元素个数nnzB 0Host 内存csrSortedValB输入const float*B 的非零元素值数组长度为 nnzBnnzB0 时可为 nullptr本函数不读取Device 内存csrSortedRowPtrB输入const int*B 的行指针数组长度为 m1m0 时可为 nullptrDevice 内存csrSortedColIndB输入const int*B 的列索引数组长度为 nnzBnnzB0 时可为 nullptrDevice 内存descrC输入const aclsparseMatDescr_t矩阵 C 的描述符仅支持ACL_SPARSE_MATRIX_TYPE_GENERAL类型Host 内存csrSortedValC输入const float*C 的非零元素值数组可为 nullptr本函数不读取Device 内存csrSortedRowPtrC输入const int*C 的行指针数组可为 nullptr本函数不读取Device 内存csrSortedColIndC输入const int*C 的列索引数组可为 nullptr本函数不读取Device 内存pBufferSizeInBytes输出size_t*输出所需 workspace 大小字节Host 内存约束说明m 0n 0nnzA 0nnzB 0handle 不可为 nullptrdescrA / descrB / descrC 不可为 nullptr且 type 仅支持ACL_SPARSE_MATRIX_TYPE_GENERALdescrA / descrB / descrC 的 indexBase 必须为ACL_SPARSE_INDEX_BASE_ZERO或ACL_SPARSE_INDEX_BASE_ONEalpha / beta 不可为 nullptr当 m 0 时csrSortedRowPtrA / csrSortedRowPtrB 不可为 nullptr当 nnzA 0 时csrSortedColIndA 不可为 nullptr当 nnzB 0 时csrSortedColIndB 不可为 nullptrpBufferSizeInBytes 不可为 nullptrworkspace 大小公式(m 1) * sizeof(int32_t)前 m 个 int32_t 用于 nnzPerRow第 m1 个用于 nnzCcsrSortedValA / csrSortedValB / csrSortedValC / csrSortedRowPtrC / csrSortedColIndC 可为 nullptr本函数不读取这些指针仅查询 workspace 大小aclsparseXcsrgeam2Nnz产品支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持函数原型aclsparseStatus_t aclsparseXcsrgeam2Nnz( aclsparseHandle_t handle, int m, int n, const aclsparseMatDescr_t descrA, int nnzA, const int *csrSortedRowPtrA, const int *csrSortedColIndA, const aclsparseMatDescr_t descrB, int nnzB, const int *csrSortedRowPtrB, const int *csrSortedColIndB, const aclsparseMatDescr_t descrC, int *csrSortedRowPtrC, int *nnzTotalDevHostPtr, void *workspace);参数说明参数名输入/输出参数类型说明handle输入aclsparseHandle_tops-sparse 库上下文句柄Host 内存m输入int矩阵行数m 0Host 内存n输入int矩阵列数n 0Host 内存descrA输入const aclsparseMatDescr_t矩阵 A 的描述符Host 内存nnzA输入int矩阵 A 的非零元素个数Host 内存csrSortedRowPtrA输入const int*A 的行指针数组长度为 m1Device 内存csrSortedColIndA输入const int*A 的列索引数组长度为 nnzADevice 内存descrB输入const aclsparseMatDescr_t矩阵 B 的描述符Host 内存nnzB输入int矩阵 B 的非零元素个数Host 内存csrSortedRowPtrB输入const int*B 的行指针数组长度为 m1Device 内存csrSortedColIndB输入const int*B 的列索引数组长度为 nnzBDevice 内存descrC输入const aclsparseMatDescr_t矩阵 C 的描述符Host 内存csrSortedRowPtrC输出int*C 的行指针数组输出长度为 m1。调用前需分配Device 内存nnzTotalDevHostPtr输出int*C 的非零元素总数 nnzC。内存位置由aclsparseSetPointerMode控制Host/Device 内存workspace输入void*workspace 缓冲区由 bufferSizeExt 返回的大小分配Device 内存约束说明m 0n 0nnzA 0nnzB 0handle 不可为 nullptrdescrA / descrB / descrC 不可为 nullptr且 type 仅支持ACL_SPARSE_MATRIX_TYPE_GENERALdescrA / descrB / descrC 的 indexBase 必须为ACL_SPARSE_INDEX_BASE_ZERO或ACL_SPARSE_INDEX_BASE_ONE当 m 0 时csrSortedRowPtrA / csrSortedRowPtrB 不可为 nullptr当 nnzA 0 时csrSortedColIndA 不可为 nullptr当 nnzB 0 时csrSortedColIndB 不可为 nullptrcsrSortedRowPtrC 不可为 nullptr调用前需分配 m1 大小的 int 数组nnzTotalDevHostPtr 不可为 nullptrworkspace 不可为 nullptr需按 bufferSizeExt 返回的大小分配当 m 0 或 n 0 时函数直接返回成功nnzC 0注意此函数使用 X 前缀大写表示与数据类型无关不涉及值数组仅操作索引结构aclsparseScsrgeam2产品支持情况Ascend 950PR / Ascend 950DT支持Atlas A3 训练系列产品 / Atlas A3 推理系列产品不支持Atlas A2 训练系列产品 / Atlas A2 推理系列产品不支持函数原型aclsparseStatus_t aclsparseScsrgeam2( aclsparseHandle_t handle, int m, int n, const float *alpha, const aclsparseMatDescr_t descrA, int nnzA, const float *csrSortedValA, const int *csrSortedRowPtrA, const int *csrSortedColIndA, const float *beta, const aclsparseMatDescr_t descrB, int nnzB, const float *csrSortedValB, const int *csrSortedRowPtrB, const int *csrSortedColIndB, const aclsparseMatDescr_t descrC, float *csrSortedValC, int *csrSortedRowPtrC, int *csrSortedColIndC, void *pBuffer);参数说明参数名输入/输出参数类型说明handle输入aclsparseHandle_tops-sparse 库上下文句柄Host 内存m输入int矩阵行数m 0Host 内存n输入int矩阵列数n 0Host 内存alpha输入const float*标量 α 指针。内存位置由aclsparseSetPointerMode控制Host/Device 内存descrA输入const aclsparseMatDescr_t矩阵 A 的描述符Host 内存nnzA输入int矩阵 A 的非零元素个数Host 内存csrSortedValA输入const float*A 的非零元素值数组长度为 nnzADevice 内存csrSortedRowPtrA输入const int*A 的行指针数组长度为 m1Device 内存csrSortedColIndA输入const int*A 的列索引数组长度为 nnzADevice 内存beta输入const float*标量 β 指针。内存位置由aclsparseSetPointerMode控制Host/Device 内存descrB输入const aclsparseMatDescr_t矩阵 B 的描述符Host 内存nnzB输入int矩阵 B 的非零元素个数Host 内存csrSortedValB输入const float*B 的非零元素值数组长度为 nnzBDevice 内存csrSortedRowPtrB输入const int*B 的行指针数组长度为 m1Device 内存csrSortedColIndB输入const int*B 的列索引数组长度为 nnzBDevice 内存descrC输入const aclsparseMatDescr_t矩阵 C 的描述符Host 内存csrSortedValC输出float*C 的非零元素值数组输出长度为 nnzCDevice 内存csrSortedRowPtrC输入int*C 的行指针数组由 Nnz 阶段填充长度为 m1Device 内存csrSortedColIndC输出int*C 的列索引数组输出长度为 nnzCDevice 内存pBuffer输入void*workspace 缓冲区由 bufferSizeExt 返回的大小分配Device 内存约束说明m 0n 0nnzA 0nnzB 0handle 不可为 nullptrdescrA / descrB / descrC 不可为 nullptr且 type 仅支持ACL_SPARSE_MATRIX_TYPE_GENERALdescrA / descrB / descrC 的 indexBase 必须为ACL_SPARSE_INDEX_BASE_ZERO或ACL_SPARSE_INDEX_BASE_ONE当 m 0 时csrSortedRowPtrA / csrSortedRowPtrB / csrSortedRowPtrC 不可为 nullptr当 nnzA 0 时csrSortedValA / csrSortedColIndA 不可为 nullptr当 nnzB 0 时csrSortedValB / csrSortedColIndB 不可为 nullptrcsrSortedValC / csrSortedColIndC 不可为 nullptr需按 nnzC 分配pBuffer 不可为 nullptr调用前必须先调用aclsparseXcsrgeam2Nnz填充csrRowPtrC和获取nnzC当 m 0 或 n 0 时函数直接返回成功支持的稀疏格式格式支持说明CSR✅A、B、C 三个矩阵均为 CSR 格式COO❌csrgeam2 仅支持 CSRCSC❌csrgeam2 仅支持 CSRCSR 格式索引结构数组长度说明csrRowPtrm 1行偏移指针csrRowPtr[i] 是第 i 行非零元素的起始索引csrColIndnnz列索引数组csrValnnz非零元素值数组索引基址通过 MatDescr 的indexBase字段指定ACL_SPARSE_INDEX_BASE_ZERO0-basedC 风格ACL_SPARSE_INDEX_BASE_ONE1-basedFortran 风格A、B、C 的索引基址可以不同各自通过独立的 MatDescr 指定。数据类型精度前缀计算类型值类型说明SFP32FP32当前唯一支持的精度S 前缀索引类型int3232 位有符号整数。调用示例示例代码如下仅供参考具体编译和执行过程请参考编译与运行样例。#include cstdio #include memory #include vector #include acl/acl.h #include cann_ops_sparse.h #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) class AclContext { public: explicit AclContext(int32_t deviceId) : deviceId_(deviceId) {} ~AclContext() { if (stream_ ! nullptr) { aclrtDestroyStream(stream_); stream_ nullptr; } if (deviceSet_) { aclrtResetDevice(deviceId_); deviceSet_ false; } if (aclInited_) { aclFinalize(); aclInited_ false; } } int Init() { auto ret aclInit(nullptr); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclInit failed. ERROR: %d\n, ret); return ret); aclInited_ true; ret aclrtSetDevice(deviceId_); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtSetDevice failed. ERROR: %d\n, ret); return ret); deviceSet_ true; ret aclrtCreateStream(stream_); CHECK_RET(ret ACL_SUCCESS, LOG_PRINT(aclrtCreateStream failed. ERROR: %d\n, ret); return ret); return ACL_SUCCESS; } aclrtStream Stream() const { return stream_; } private: int32_t deviceId_; aclrtStream stream_ nullptr; bool aclInited_ false; bool deviceSet_ false; }; // 辅助分配 Device 内存并拷贝 Host 数据 static void* AllocAndCopyDevice(void *hostPtr, size_t sizeBytes) { void *dPtr nullptr; aclrtMalloc(dPtr, sizeBytes, ACL_MEM_MALLOC_HUGE_FIRST); if (hostPtr ! nullptr sizeBytes 0) { aclrtMemcpy(dPtr, sizeBytes, hostPtr, sizeBytes, ACL_MEMCPY_HOST_TO_DEVICE); } return dPtr; } int aclsparseCsrgeam2Test(AclContext ctx) { aclrtStream stream ctx.Stream(); // 1. 创建 ops-sparse 句柄 aclsparseHandle_t rawHandle nullptr; auto sparseRet aclsparseCreate(rawHandle); CHECK_RET(sparseRet ACL_SPARSE_STATUS_SUCCESS, LOG_PRINT(aclsparseCreate failed: %d\n, sparseRet); return sparseRet); std::unique_ptraclsparseContext, aclsparseStatus_t (*)(aclsparseHandle_t) handlePtr(rawHandle, aclsparseDestroy); aclsparseSetStream(handlePtr.get(), stream); aclsparseSetPointerMode(handlePtr.get(), ACL_SPARSE_POINTER_MODE_HOST); // 2. 准备 Host 端 CSR 数据 // 示例两个 3x3 的稀疏矩阵 A 和 B // // A (3x3, nnzA4): B (3x3, nnzB2): // [1.0 0.0 2.0] [0.0 0.0 5.0] // [0.0 4.0 0.0] [6.0 0.0 0.0] // [3.0 0.0 0.0] [0.0 0.0 0.0] // // C 1.0 * A 1.0 * B: // C[0] [1.0, 0.0, 7.0 ] (nnz: 2) // C[1] [6.0, 4.0, 0.0 ] (nnz: 2) // C[2] [3.0, 0.0, 0.0 ] (nnz: 1) // nnzC 5 int m 3; int n 3; int nnzA 4; int nnzB 2; float hAlpha 1.0f; float hBeta 1.0f; // A: CSR 数据 (3x3, nnzA4) std::vectorint hRowPtrA {0, 2, 3, 4}; std::vectorint hColIndA {0, 2, 1, 0}; std::vectorfloat hValA {1.0f, 2.0f, 4.0f, 3.0f}; // B: CSR 数据 (3x3, nnzB2) std::vectorint hRowPtrB {0, 1, 2, 2}; std::vectorint hColIndB {2, 0}; std::vectorfloat hValB {5.0f, 6.0f}; // 3. 创建 MatDescrA/B/C 各自独立 aclsparseMatDescr_t descrA nullptr, descrB nullptr, descrC nullptr; aclsparseCreateMatDescr(descrA); aclsparseCreateMatDescr(descrB); aclsparseCreateMatDescr(descrC); aclsparseSetMatType(descrA, ACL_SPARSE_MATRIX_TYPE_GENERAL); aclsparseSetMatType(descrB, ACL_SPARSE_MATRIX_TYPE_GENERAL); aclsparseSetMatType(descrC, ACL_SPARSE_MATRIX_TYPE_GENERAL); aclsparseSetMatIndexBase(descrA, ACL_SPARSE_INDEX_BASE_ZERO); aclsparseSetMatIndexBase(descrB, ACL_SPARSE_INDEX_BASE_ZERO); aclsparseSetMatIndexBase(descrC, ACL_SPARSE_INDEX_BASE_ZERO); // 4. 拷贝 A/B 的 CSR 数据到 Device void *dRowPtrA AllocAndCopyDevice(hRowPtrA.data(), (m 1) * sizeof(int)); void *dColIndA AllocAndCopyDevice(hColIndA.data(), nnzA * sizeof(int)); void *dValA AllocAndCopyDevice(hValA.data(), nnzA * sizeof(float)); void *dRowPtrB AllocAndCopyDevice(hRowPtrB.data(), (m 1) * sizeof(int)); void *dColIndB AllocAndCopyDevice(hColIndB.data(), nnzB * sizeof(int)); void *dValB AllocAndCopyDevice(hValB.data(), nnzB * sizeof(float)); // 5. Step 1 — bufferSizeExt: 查询 workspace 大小 size_t bufferSize 0; sparseRet aclsparseScsrgeam2_bufferSizeExt( handlePtr.get(), m, n, hAlpha, descrA, nnzA, static_castconst float*(dValA), static_castconst int*(dRowPtrA), static_castconst int*(dColIndA), hBeta, descrB, nnzB, static_castconst float*(dValB), static_castconst int*(dRowPtrB), static_castconst int*(dColIndB), descrC, nullptr, nullptr, nullptr, bufferSize); CHECK_RET(sparseRet ACL_SPARSE_STATUS_SUCCESS, LOG_PRINT(bufferSizeExt failed: %d\n, sparseRet); return sparseRet); LOG_PRINT(bufferSize %zu bytes\n, bufferSize); // 分配 workspace void *dWorkspace nullptr; aclrtMalloc(dWorkspace, bufferSize, ACL_MEM_MALLOC_HUGE_FIRST); // 6. Step 2 — Xcsrgeam2Nnz: 计算 C 的 csrRowPtrC 和 nnzC // 预分配 csrRowPtrC (m1) void *dRowPtrC nullptr; aclrtMalloc(dRowPtrC, (m 1) * sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST); int nnzC 0; // HOST 模式下nnzC 直接写入 host 变量 sparseRet aclsparseXcsrgeam2Nnz( handlePtr.get(), m, n, descrA, nnzA, static_castconst int*(dRowPtrA), static_castconst int*(dColIndA), descrB, nnzB, static_castconst int*(dRowPtrB), static_castconst int*(dColIndB), descrC, static_castint*(dRowPtrC), nnzC, // HOST 指针 dWorkspace); CHECK_RET(sparseRet ACL_SPARSE_STATUS_SUCCESS, LOG_PRINT(Xcsrgeam2Nnz failed: %d\n, sparseRet); return sparseRet); LOG_PRINT(nnzC %d\n, nnzC); // 7. Step 3 — Scsrgeam2: 计算 C 的列索引和值 void *dColIndC nullptr; void *dValC nullptr; aclrtMalloc(dColIndC, nnzC * sizeof(int), ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(dValC, nnzC * sizeof(float), ACL_MEM_MALLOC_HUGE_FIRST); // 分配主计算 pBuffer可与 Nnz 阶段的 workspace 共用或独立分配 void *dPBuffer nullptr; aclrtMalloc(dPBuffer, bufferSize, ACL_MEM_MALLOC_HUGE_FIRST); sparseRet aclsparseScsrgeam2( handlePtr.get(), m, n, hAlpha, descrA, nnzA, static_castconst float*(dValA), static_castconst int*(dRowPtrA), static_castconst int*(dColIndA), hBeta, descrB, nnzB, static_castconst float*(dValB), static_castconst int*(dRowPtrB), static_castconst int*(dColIndB), descrC, static_castfloat*(dValC), static_castint*(dRowPtrC), static_castint*(dColIndC), dPBuffer); CHECK_RET(sparseRet ACL_SPARSE_STATUS_SUCCESS, LOG_PRINT(Scsrgeam2 failed: %d\n, sparseRet); return sparseRet); // 8. 同步等待计算完成 aclrtSynchronizeStream(stream); // 9. 将结果拷贝回 Host 并打印 std::vectorint hRowPtrC(m 1, 0); std::vectorint hColIndC(nnzC, 0); std::vectorfloat hValC(nnzC, 0.0f); aclrtMemcpy(hRowPtrC.data(), (m 1) * sizeof(int), dRowPtrC, (m 1) * sizeof(int), ACL_MEMCPY_DEVICE_TO_HOST); aclrtMemcpy(hColIndC.data(), nnzC * sizeof(int), dColIndC, nnzC * sizeof(int), ACL_MEMCPY_DEVICE_TO_HOST); aclrtMemcpy(hValC.data(), nnzC * sizeof(float), dValC, nnzC * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); LOG_PRINT(\nResult C (CSR):\n); LOG_PRINT( rowPtr: ); for (int i 0; i m; i) { LOG_PRINT(%d , hRowPtrC[i]); } LOG_PRINT(\n colInd: ); for (int i 0; i nnzC; i) { LOG_PRINT(%d , hColIndC[i]); } LOG_PRINT(\n val: ); for (int i 0; i nnzC; i) { LOG_PRINT(%.1f , hValC[i]); } LOG_PRINT(\n); // 10. 清理资源 aclsparseDestroyMatDescr(descrA); aclsparseDestroyMatDescr(descrB); aclsparseDestroyMatDescr(descrC); if (dRowPtrA) aclrtFree(dRowPtrA); if (dColIndA) aclrtFree(dColIndA); if (dValA) aclrtFree(dValA); if (dRowPtrB) aclrtFree(dRowPtrB); if (dColIndB) aclrtFree(dColIndB); if (dValB) aclrtFree(dValB); if (dRowPtrC) aclrtFree(dRowPtrC); if (dColIndC) aclrtFree(dColIndC); if (dValC) aclrtFree(dValC); if (dWorkspace) aclrtFree(dWorkspace); if (dPBuffer) aclrtFree(dPBuffer); return ACL_SPARSE_STATUS_SUCCESS; } int main() { AclContext ctx(0); auto ret ctx.Init(); CHECK_RET(ret ACL_SUCCESS, return ret); ret aclsparseCsrgeam2Test(ctx); CHECK_RET(ret ACL_SPARSE_STATUS_SUCCESS, LOG_PRINT(aclsparseCsrgeam2Test failed: %d\n, ret); return ret); return 0; }预期输出如下bufferSize 16 bytes nnzC 5 Result C (CSR): rowPtr: 0 2 4 5 colInd: 0 2 0 1 0 val: 1.0 7.0 6.0 4.0 3.0【免费下载链接】ops-sparse本项目是CANN提供的高性能稀疏矩阵计算的算子库专注于优化稀疏矩阵的计算效率。项目地址: https://gitcode.com/cann/ops-sparse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考