当前位置: 首页 > news >正文

CANN/sip Cgemm复数矩阵乘法

Cgemm

【免费下载链接】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×

功能说明

  • 接口功能:
    asdBlasMakeCgemmPlan:初始化该句柄对应的Cgemm算子配置。
    asdBlasCgemm:矩阵乘法运算中的一种,用于计算两个复数矩阵的乘积。
  • 计算公式: $$ C= alpha * op(A)*op(B) + beta * C\ 其中,op(X)= X \ \ \ \text{or} \ \ \ op(X) = X^T \ \ \ \text{or} \ \ \ op(X) = X^H $$ 示例:
    输入“inTensorA”为:
    [ [ 1+i, 1+2i ], [ 1+3i, 1+4i ] ]
    输入“inTensorB”为:
    [ [ 2+i, 2+2i ], [ 2+3i, 2+4i ] ]
    输入“inTensorC”为:
    [ [ 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。
    调用“Cgemm”算子后,输出“outTensor”为:
    [ [ -15+19i, -27+19i ], [ -37+21i, -57+13i ] ]

函数原型

AspbStatus asdBlasMakeCgemmPlan( asdBlasHandle handle, asdBlasOperation_t transa, asdBlasOperation_t transb, int64_t m, int64_t n, int64_t k, int64_t lda, int64_t ldb, int64_t ldc)
AspbStatus asdBlasCgemm( 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)

asdBlasMakeCgemmPlan

  • 参数说明:

    参数名输入/输出描述
    handle(asdBlasHandle)输入算子的句柄
    transa(asdBlasOperation_t)输入指定矩阵A是否需要转置。
    • ASDBLAS_OP_N:不转置
    • ASDBLAS_OP_T:转置
    • ASDBLAS_OP_C:共轭转置
    transb(asdBlasOperation_t)输入指定矩阵B是否需要转置。
    • ASDBLAS_OP_N:不转置
    • ASDBLAS_OP_T:转置
    • ASDBLAS_OP_C:共轭转置
    m(int64_t)输入矩阵A和C的行数。
    n(int64_t)输入矩阵B和C的列数。
    k(int64_t)输入矩阵A和B的公共维度。
    lda( int64_t)输入矩阵A左右相邻元素间的内存地址偏移量(当前约束为m)。
    ldb( int64_t)输入矩阵B左右相邻元素间的内存地址偏移量(当前约束为k)。
    ldc( int64_t)输入矩阵C左右相邻元素间的内存地址偏移量(当前约束为m)。
  • 返回值

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

asdBlasCgemm

  • 参数说明:

    参数名输入/输出描述
    handle(asdBlasHandle)输入算子的句柄
    transa(asdBlasOperation_t)输入指定矩阵A是否需要转置。
    • ASDBLAS_OP_N:不转置
    • ASDBLAS_OP_T:转置
    • ASDBLAS_OP_C:共轭转置
    transb(asdBlasOperation_t)输入指定矩阵B是否需要转置。
    • ASDBLAS_OP_N:不转置
    • ASDBLAS_OP_T:转置
    • ASDBLAS_OP_C:共轭转置
    m(int64_t)输入矩阵C的行数。
    n(int64_t)输入矩阵C的列数。
    k( int64_t)输入矩阵A和B的公共维度。
    lda( int64_t)输入矩阵A左右相邻元素间的内存地址偏移量(当前约束为m)。
    ldb( int64_t)输入矩阵B左右相邻元素间的内存地址偏移量(当前约束为k)。
    ldc( int64_t)输入矩阵C左右相邻元素间的内存地址偏移量(当前约束为m)。
    A(aclTensor *)输入
    • 输入的矩阵,对应公式中的'A'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    B(aclTensor *)输入
    • 输入的矩阵,对应公式中的'B'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    C(aclTensor *)输入/输出
    • 输入/输出的矩阵,对应公式中的'c'
    • 数据类型支持COMPLEX64。
    • 数据格式支持ND。
    • shape为[m,n]。
    alpha(std::complex&ltfloat> *)输入对应公式中的alpha,复数标量,用于乘以矩阵乘法的结果。
  • 返回值

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

约束说明

  • 输入的元素个数m,n,k当前覆盖支持[1,8192]。
  • 算子输入数据为列主序,输入shape为[m,k]、[k,n]、[m,n],输出shape为[m,n]。
  • 算子实际计算时,不支持ND高维度运算(不支持维度≥3的运算)。

调用示例

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

#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 rows, int64_t cols) { for (int64_t i = 0; i < rows; i++) { for (int64_t j = 0; j < cols; j++) { std::cout << tensorData[i * cols + j] << " "; } 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 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, 1.0f); std::complex<float> beta = std::complex<float>(2.0f, 2.0f); int64_t lda = m; int64_t ldb = k; int64_t ldc = m; const int64_t tensorASize = m * k; const int64_t tensorBSize = k * n; const int64_t tensorCSize = 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 = {m, k}; std::vector<int64_t> matBShape = {k, n}; std::vector<int64_t> matCShape = {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 = " << alpha << std::endl; std::cout << "beta = " << beta << std::endl; std::cout << "------- input TensorInA -------" << std::endl; printTensor(tensorInAData, m, k); std::cout << "------- input TensorInB -------" << std::endl; printTensor(tensorInBData, k, n); asdBlasHandle handle; asdBlasCreate(handle); size_t lwork = 0; void *buffer = nullptr; asdBlasMakeCgemmPlan(handle, transA, transB, m, n, k, lda, ldb, ldc); 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(asdBlasCgemm(handle, transA, transB, m, n, k, alpha, matA, lda, matB, ldb, beta, matC, ldc)); 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, 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),仅供参考

http://www.jsqmd.com/news/785122/

相关文章:

  • 宁波地区专业的银行活动策划生产厂家找哪家 - GrowthUME
  • Linux Mem -- 通过reserved-memory缩减内存
  • 前端高级开发工程师面试准备一
  • 【GitHub】SuperClaude Framework深度解析:将Claude Code打造为专业开发平台的元编程配置框架
  • AI 术语通俗词典:偏导数
  • 量子机器学习新范式:Classiq如何简化QML模型开发
  • 大众认为花钱进修一定能升职加薪,编程统计进修投入,职业晋升数据,无用进修只会增加个人经济负担。
  • 构建AI教育互操作生态:从数据孤岛到标准化学习系统
  • 沈阳本地CPPM官方授权报名中心及联系方式 - 众智商学院课程中心
  • SLING实战:如何构建自己的知识抽取系统
  • 管程与线程:从操作系统到编程语言
  • Sanic中间件链优化终极指南:构建高性能请求处理流水线
  • CANN驱动HBM厂商查询
  • 物理模拟算法Algorithms39:刚体动力学与碰撞检测终极指南
  • 终极BullshitGenerator语料库解析:解锁100+名人名言的高效使用指南
  • 如何理解KityMinder脑图编辑器的模块化命令系统设计原理 [特殊字符]
  • 深耕北京暖居,铸就品质标杆——宝鹿散热器品牌全解析 - GrowthUME
  • 地学基础模型:构建地球科学通用AI大脑的技术架构与实践
  • 第十章 用Java实现JVM之本地方法调用
  • Nuxt.js Auth模块与Laravel后端集成:JWT、Passport、Sanctum完整指南
  • CANN双三次上采样反向传播算子
  • 2026年AI Agent开发部署公司推荐指南:五大服务商多维度对比分析
  • 终极指南:Crypto-JS如何应对量子计算威胁?5个关键安全策略解析
  • 对比使用前后Taotoken在API调用延迟与稳定性上的体感差异
  • CANN/asc-devkit AddOutputTd函数
  • 浅析操作系统中的死锁问题及银行家算法
  • x265编码器深度解析:SAO模块技术详解
  • Linux配置IgH实现EtherCAT主战
  • 想选高性价比光伏支架?这些厂家值得你深入了解! - GrowthUME
  • 运维还在靠人肉排障?AI 运维时代已经开始“自己修自己”了