news 2026/5/9 18:53:20

CANN/sip CgemmBatched算子

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN/sip CgemmBatched算子

HCgemmBatched

【免费下载链接】sip本项目是CANN提供的一款高效、可靠的高性能信号处理算子加速库,基于华为Ascend AI处理器,专门为信号处理领域而设计。项目地址: https://gitcode.com/cann/sip

产品支持情况

产品是否支持
Atlas 200I/500 A2 推理产品×
Atlas 推理系列产品×
Atlas 训练系列产品×
Atlas A3 训练系列产品/Atlas A3 推理系列产品
Atlas A2 训练系列产品/Atlas A2 推理系列产品
Ascend 950PR/Ascend 950DT×

功能说明

  • 接口功能:
    asdBlasMakeCgemmBatchedPlan:初始化该句柄对应的算子配置。
    asdBlasCgemmBatched:用于计算两批复数矩阵的乘积。
  • 计算公式: $$ C= alpha * op(A[i])*op(B[i]) + beta * C[i] $$ 示例:
    输入“inTensorA[i]”为:
    [ [ 1+i, 1+2i ], [ 1+3i, 1+4i ] ]
    输入“inTensorB[i]”为:
    [ [ 2+i, 2+2i ], [ 2+3i, 2+4i ] ]
    输入“inTensorC[i]”为:
    [ [ 3+i, 3+2i ], [ 3+3i, 3+4i ] ]
    输入“transa”为: N,输入“transb”为:T。
    输入“m”为:2,输入“n”为: 2,输入“k”为:2,输入“alpha”为:1+i,“beta”为:2+2i。
    输入“lda”为: 2,输入“ldb”为:2,输入“ldc”为:2。
    输入“batchCount”为:1。
    调用“asdBlasCgemmBatched”算子后,输出“C”为:
    [ [ -15+19i, -27+19i ], [ -37+21i, -57+13i ] ]

函数原型

AspbStatus asdBlasMakeCgemmBatchedPlan( asdBlasHandle handle)
AspbStatus asdBlasCgemmBatched( asdBlasHandle handle, asdBlasOperation_t transa, asdBlasOperation_t transb, const int64_t m, const int64_t n, const int64_t k, const std::complex<float> & alpha, aclTensor * A, const int64_t lda, aclTensor * B, const int64_t ldb, const std::complex<float> & beta, aclTensor * C, const int64_t ldc, const int64_t batchCount)

asdBlasMakeCgemmBatchedPlan

  • 参数说明:

    参数名输入/输出描述
    handle(asdBlasHandle)输入算子的句柄
  • 返回值

    返回状态码,具体参见SiP返回码。

asdBlasCgemmBatched

  • 参数说明:

    参数名输入/输出描述
    handle(asdBlasHandle)输入算子的句柄
    transa(asdBlasOperation_t)输入指定矩阵A是否需要转置,取值必须为ASDBLAS_OP_N。
    transb(asdBlasOperation_t)输入指定矩阵B是否需要转置,取值必须为ASDBLAS_OP_N。
    m(int64_t)输入矩阵C的行数,取值范围为:{1-32}。
    n(int64_t)输入矩阵C的列数,取值范围为:{1-32}。
    k( int64_t)输入矩阵A和B的公共维度,取值范围为:{1-32}。
    lda( int64_t)输入A左右相邻元素间的内存地址偏移量,取值和k相等。
    ldb( int64_t)输入B左右相邻元素间的内存地址偏移量,取值和n相等。
    ldc( int64_t)输入C左右相邻元素间的内存地址偏移量,取值和n相等。
    A(aclTensor *)输入
    • 输入的矩阵,对应公式中的'A'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    • shape为[batchCount, m, k]。
    B(aclTensor *)输入
    • 输入的矩阵,对应公式中的'B'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    • shape为[batchCount, k, n]。
    C(aclTensor *)输出
    • 对应公式中的'C'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    • shape为[batchCount, m, n]。
    alpha(std::complex<float> &)输入对应公式中的alpha,复数标量,用于乘以矩阵乘法的结果,取值必须为1+0j。
    beta(std::complex<float> &)输入对应公式中的beta,复数标量,用于乘以矩阵C。取值必须为 0+0j。。
    batchCount(int64_t)输入批次数量。取值范围为{12 - 26208}。
  • 返回值

    返回状态码,具体参见SiP返回码。

约束说明

  • 算子实际计算时,只支持3维ND运算。
  • 算子输入数据为行主序,输入shape为[batchCount, m, k]、[batchCount, k, n]、[batchCount, m, n],输出shape为[batchCount, m, n]。

调用示例

示例代码如下,该样例旨在提供快速上手、开发和调试算子的最小化实现,其核心目标是使用最精简的代码展示算子的核心功能,而非提供生产级的安全保障。不推荐用户直接将示例代码作为业务代码,若用户将示例代码应用在自身的真实业务场景中且发生了安全问题,则需用户自行承担。

#include <iostream> #include <vector> #include "asdsip.h" #include "acl/acl.h" #include "acl_meta.h" using namespace AsdSip; #define ASD_STATUS_CHECK(err) \ do { \ AsdSip::AspbStatus err_ = (err); \ if (err_ != AsdSip::ErrorType::ACL_SUCCESS) { \ std::cout << "Execute failed." << std::endl; \ exit(-1); \ } else { \ std::cout << "Execute successfully." << std::endl; \ } \ } while (0) #define CHECK_RET(cond, return_expr) \ do { \ if (!(cond)) { \ return_expr; \ } \ } while (0) #define LOG_PRINT(message, ...) \ do { \ printf(message, ##__VA_ARGS__); \ } while (0) int64_t GetShapeSize(const std::vector<int64_t> &shape) { int64_t shapeSize = 1; for (auto i : shape) { shapeSize *= i; } return shapeSize; } int Init(int32_t deviceId, aclrtStream *stream) { // 固定写法,acl初始化 auto ret = aclInit(nullptr); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); ret = aclrtSetDevice(deviceId); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); ret = aclrtCreateStream(stream); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); return 0; } template <typename T> int CreateAclTensor(const std::vector<T> &hostData, const std::vector<int64_t> &shape, void **deviceAddr, aclDataType dataType, aclTensor **tensor) { auto size = GetShapeSize(shape) * sizeof(T); // 调用aclrtMalloc申请device侧内存 auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); // 调用aclrtMemcpy将host侧数据复制到device侧内存上 ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); // 计算连续tensor的strides std::vector<int64_t> strides(shape.size(), 1); for (int64_t i = shape.size() - 2; i >= 0; i--) { strides[i] = shape[i + 1] * strides[i + 1]; } // 调用aclCreateTensor接口创建aclTensor *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); return 0; } void printTensor(std::vector<std::complex<float>> tensorData, int64_t batch, int64_t rows, int64_t cols) { for (int64_t b = 0; b < batch; b++) { for (int64_t i = 0; i < rows; i++) { for (int64_t j = 0; j < cols; j++) { auto data = tensorData[b * rows * cols + i * cols + j]; std::cout << "(" << (float)data.real() << "," << (float)data.imag() << ")" << " "; } std::cout << std::endl; } std::cout << std::endl; } } int main(int argc, char **argv) { int deviceId = 0; aclrtStream stream; auto ret = Init(deviceId, &stream); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); int batch = 2; int m = 3; int k = 3; int n = 3; asdBlasOperation_t transA = asdBlasOperation_t::ASDBLAS_OP_N; asdBlasOperation_t transB = asdBlasOperation_t::ASDBLAS_OP_N; std::complex<float> alpha = std::complex<float>(1.0f, 0.0f); std::complex<float> beta = std::complex<float>(0.0f, 0.0f); int64_t lda = k; int64_t ldb = n; int64_t ldc = n; const int64_t tensorASize = batch * m * k; const int64_t tensorBSize = batch * k * n; const int64_t tensorCSize = batch * m * n; std::vector<std::complex<float>> tensorInAData; tensorInAData.reserve(tensorASize); for (int i = 0; i < tensorASize; i++) { tensorInAData.push_back(std::complex<float>(1.0f, i + 0.0f)); } std::vector<std::complex<float>> tensorInBData; tensorInBData.reserve(tensorBSize); for (int i = 0; i < tensorBSize; i++) { tensorInBData.push_back(std::complex<float>(1.0f, i + 0.0f)); } std::vector<std::complex<float>> tensorInCData; tensorInCData.reserve(tensorCSize); for (int i = 0; i < tensorCSize; i++) { tensorInCData.push_back(std::complex<float>(1.0f, i + 0.0f)); } std::vector<int64_t> matAShape = {batch, m, k}; std::vector<int64_t> matBShape = {batch, k, n}; std::vector<int64_t> matCShape = {batch, m, n}; aclTensor *matA = nullptr; aclTensor *matB = nullptr; aclTensor *matC = nullptr; void *matADeviceAddr = nullptr; void *matBDeviceAddr = nullptr; void *matCDeviceAddr = nullptr; ret = CreateAclTensor<std::complex<float>>( tensorInAData, matAShape, &matADeviceAddr, aclDataType::ACL_COMPLEX64, &matA); CHECK_RET(ret == ::ACL_SUCCESS, return ret); ret = CreateAclTensor<std::complex<float>>( tensorInBData, matBShape, &matBDeviceAddr, aclDataType::ACL_COMPLEX64, &matB); CHECK_RET(ret == ::ACL_SUCCESS, return ret); ret = CreateAclTensor<std::complex<float>>( tensorInCData, matCShape, &matCDeviceAddr, aclDataType::ACL_COMPLEX64, &matC); CHECK_RET(ret == ::ACL_SUCCESS, return ret); std::cout << "alpha = " << "(" << (float) alpha.real() << "," << (float) alpha.imag() << ")" << std::endl; std::cout << "beta = " << "(" << (float) beta.real() << "," << (float) beta.imag() << ")" << std::endl; std::cout << "------- input TensorInA -------" << std::endl; printTensor(tensorInAData, batch, m, k); std::cout << "------- input TensorInB -------" << std::endl; printTensor(tensorInBData, batch, k, n); asdBlasHandle handle; asdBlasCreate(handle); size_t lwork = 0; void *buffer = nullptr; asdBlasMakeCgemmBatchedPlan(handle); asdBlasGetWorkspaceSize(handle, lwork); std::cout << "lwork = " << lwork << std::endl; if (lwork > 0) { ret = aclrtMalloc(&buffer, static_cast<int64_t>(lwork), ACL_MEM_MALLOC_HUGE_FIRST); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); } asdBlasSetWorkspace(handle, buffer); asdBlasSetStream(handle, stream); ASD_STATUS_CHECK(asdBlasCgemmBatched(handle, transA, transB, m, n, k, alpha, matA, lda, matB, ldb, beta, matC, ldc, batch)); asdBlasSynchronize(handle); asdBlasDestroy(handle); ret = aclrtMemcpy(tensorInCData.data(), tensorCSize * sizeof(std::complex<float>), matCDeviceAddr, tensorCSize * sizeof(std::complex<float>), ACL_MEMCPY_DEVICE_TO_HOST); CHECK_RET(ret == ::ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); std::cout << "------- output TensorInC -------" << std::endl; printTensor(tensorInCData, batch, m, n); aclDestroyTensor(matA); aclDestroyTensor(matB); aclDestroyTensor(matC); aclrtFree(matADeviceAddr); aclrtFree(matBDeviceAddr); aclrtFree(matCDeviceAddr); aclrtDestroyStream(stream); aclrtResetDevice(deviceId); aclFinalize(); return 0; }

【免费下载链接】sip本项目是CANN提供的一款高效、可靠的高性能信号处理算子加速库,基于华为Ascend AI处理器,专门为信号处理领域而设计。项目地址: https://gitcode.com/cann/sip

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

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

图数据库与记忆体融合:构建AI智能体的结构化记忆系统

1. 项目概述&#xff1a;当图数据库遇上记忆体&#xff0c;会擦出怎样的火花&#xff1f;最近在折腾一些需要处理复杂关系数据的项目时&#xff0c;我一直在寻找一个能同时搞定“关系存储”和“上下文记忆”的解决方案。传统的做法要么是把数据一股脑塞进图数据库&#xff0c;然…

作者头像 李华
网站建设 2026/5/9 18:48:30

Jasminum中文文献元数据抓取插件:3步解决Zotero中文文献识别难题

Jasminum中文文献元数据抓取插件&#xff1a;3步解决Zotero中文文献识别难题 【免费下载链接】jasminum A Zotero add-on to retrive CNKI meta data. 一个简单的Zotero 插件&#xff0c;用于识别中文元数据 项目地址: https://gitcode.com/gh_mirrors/ja/jasminum 还在…

作者头像 李华
网站建设 2026/5/9 18:48:29

AGI与IoT融合实战:从架构设计到场景落地的挑战与策略

1. 项目概述&#xff1a;当通用智能遇见万物互联最近几年&#xff0c;我身边搞算法的朋友和做硬件的兄弟&#xff0c;聊天的画风越来越趋同。以前是“我这边新模型准确率又提升了几个点”&#xff0c;现在是“你这个传感器数据怎么接进我的推理管道”。这种变化背后&#xff0c…

作者头像 李华
网站建设 2026/5/9 18:48:07

AI生物技术安全新范式:紫队测试构建内生安全防线

1. 项目概述&#xff1a;当AI遇见生物技术&#xff0c;我们如何驾驭这头“猛兽”&#xff1f;在过去的几年里&#xff0c;我亲眼见证了人工智能从实验室的奇思妙想&#xff0c;迅速演变为驱动各行各业变革的核心引擎。从精准医疗中的药物发现&#xff0c;到农业领域的作物表型分…

作者头像 李华
网站建设 2026/5/9 18:45:12

CANN/driver设备故障查询API

dcmi_get_device_errorinfo 【免费下载链接】driver 本项目是CANN提供的驱动模块&#xff0c;实现基础驱动和资源管理及调度等功能&#xff0c;使能昇腾芯片。 项目地址: https://gitcode.com/cann/driver 函数原型 int dcmi_get_device_errorinfo(int card_id, int de…

作者头像 李华
网站建设 2026/5/9 18:43:20

NetBox硬件代理:自动化数据中心资产发现与同步实践

1. 项目概述&#xff1a;当硬件资产遇见NetBox在数据中心和大型IT基础设施的管理中&#xff0c;资产信息的准确性和实时性一直是个老大难问题。你肯定遇到过这种情况&#xff1a;新上了一批服务器&#xff0c;运维同学吭哧吭哧地在表格里录入了一遍信息&#xff0c;网络同学又手…

作者头像 李华