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

CANN/sip复数矩阵批量乘法

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×

功能说明

  • 接口功能:
    asdBlasMakeHCgemmBatchedPlan:初始化该句柄对应的算子配置。
    asdBlasHCgemmBatched:用于计算复数矩阵的乘积。
  • 计算公式: $$ 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”为: ASDBLAS_OP_N,输入“transb”为:ASDBLAS_OP_N。
    输入“m”为:2,输入“n”为: 2,输入“k”为:2,输入“alpha”为:1+i,“beta”为:2+2i。
    输入“lda”为: 2,输入“ldb”为:2,输入“ldc”为:2。
    输入“batchCount”为:1。
    调用“asdBlasHCgemmBatched”算子后,输出“C”为:
    [ [ -15+19i, -27+19i ], [ -37+21i, -57+13i ] ]

函数原型

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

asdBlasMakeHCgemmBatchedPlan

  • 参数说明:

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

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

asdBlasHCgemmBatched

  • 参数说明:

    参数名输入/输出描述
    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'
    • 数据类型支持COMPLEX32。
    • 数据格式支持ND。
    • shape为[batchCount, m, k]。
    B(aclTensor *)输入
    • 输入的矩阵,对应公式中的'B'
    • 数据类型支持COMPLEX32。
    • 数据格式支持ND。
    • shape为[batchCount, k, n]。
    C(aclTensor *)输出
    • 对应公式中的'C'
    • 数据类型支持COMPLEX32。
    • 数据格式支持ND。
    • shape为[batchCount, m, n]。
    alpha (std::complex<op::fp16_t> &)输入对应公式中的alpha,复数标量,用于乘以矩阵乘法的结果,取值必须为1+0j。
    beta(std::complex<op::fp16_t> &)输入对应公式中的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<op::fp16_t>> 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<op::fp16_t> alpha = std::complex<op::fp16_t>(1.0f, 0.0f); std::complex<op::fp16_t> beta = std::complex<op::fp16_t>(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<op::fp16_t>> tensorInAData; tensorInAData.reserve(tensorASize); for (int i = 0; i < tensorASize; i++) { tensorInAData.push_back(std::complex<op::fp16_t>(1.0f, i + 0.0f)); } std::vector<std::complex<op::fp16_t>> tensorInBData; tensorInBData.reserve(tensorBSize); for (int i = 0; i < tensorBSize; i++) { tensorInBData.push_back(std::complex<op::fp16_t>(1.0f, i + 0.0f)); } std::vector<std::complex<op::fp16_t>> tensorInCData; tensorInCData.reserve(tensorCSize); for (int i = 0; i < tensorCSize; i++) { tensorInCData.push_back(std::complex<op::fp16_t>(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<op::fp16_t>>( tensorInAData, matAShape, &matADeviceAddr, aclDataType::ACL_COMPLEX32, &matA); CHECK_RET(ret == ::ACL_SUCCESS, return ret); ret = CreateAclTensor<std::complex<op::fp16_t>>( tensorInBData, matBShape, &matBDeviceAddr, aclDataType::ACL_COMPLEX32, &matB); CHECK_RET(ret == ::ACL_SUCCESS, return ret); ret = CreateAclTensor<std::complex<op::fp16_t>>( tensorInCData, matCShape, &matCDeviceAddr, aclDataType::ACL_COMPLEX32, &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; asdBlasMakeHCgemmBatchedPlan(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(asdBlasHCgemmBatched(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<op::fp16_t>), matCDeviceAddr, tensorCSize * sizeof(std::complex<op::fp16_t>), 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),仅供参考

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

相关文章:

  • slim-mcp:为AI Agent工具列表智能瘦身,节省70%上下文Token
  • 2026年北京市外资研发中心认定申报要点
  • 5分钟实战指南:掌握Xenos Windows DLL注入器的完整操作流程
  • Nodejs后端服务如何接入Taotoken多模型API接口
  • 河北沧州企业认定市级、省级、国家级企业技术中心有多少奖补?
  • 如何在本地 Docker 环境中部署 DeepSeek API 转发网关服务
  • 基于Kubernetes Operator的大模型推理服务云原生部署实践
  • CANN/opbase SmallVector接口
  • 2025年东莞高职院校深度解析:广东酒店管理职业技术学院凭什么成为本地学子首选? - 品牌策略师
  • 2026年4月市面上诚信的复叶槭批发基地种植推荐,紫薇/红叶李/金森女贞/丝棉木/苗木/红叶石楠,复叶槭批发基地种植推荐 - 品牌推荐师
  • 申请高新技术企业需要几个专利?有要求吗?
  • 终极输入法词库转换指南:3分钟搞定20+输入法格式迁移
  • Python如何下载文件:从基础到进阶的完整指南
  • Godot 4双网格瓦片地图系统:解耦逻辑与渲染的进阶实践
  • APC:统一管理AI编程工具配置,告别配置孤岛与同步困境
  • Video DownloadHelper CoApp终极指南:从零开始高效下载与转换视频
  • DeepSeek-TUI:终端里的 AI 编码 Agent
  • Lumberjack Theme:基于TypeScript引擎的精准VS Code主题设计与工程实践
  • G-Helper完整指南:5分钟掌握华硕笔记本终极控制工具
  • GitHub Actions部署AI智能体:零成本实现代码仓库自动化管理与自我进化
  • 深度强化学习驱动的AIGC语义通信资源分配优化框架详解
  • VPM:硬件设计的包管理器革命,解决Verilog依赖管理难题
  • 拓扑量子计算与Sine-Cosine链模型解析
  • GEO工具实战:提升网站在AI搜索中的可见性与引用率
  • MySQL-基础篇-SQL
  • PCIe验证挑战与MVC解决方案解析
  • Jasminum:Zotero中文文献元数据抓取终极解决方案,如何彻底解决中文PDF识别难题?
  • 【2026全球AI技术大会倒计时警报】:距官方报名截止仅剩72小时,错过再等365天!
  • 基于依赖矩阵的代码架构分析:从AST解析到架构质量度量
  • 基于Claude AI的ASO自动化审计:架构、实现与工程实践