本文基于CANN开源社区的cann-sdk仓库进行技术解读
- CANN仓库地址:https://atomgit.com/cann
- 仓库链接:https://atomgit.com/cann/cann-sdk
前言
想要基于CANN开发NPU应用?需要各种工具、库、文档……
cann-sdk就是CANN的软件开发工具包(SDK),它集成了开发NPU应用所需的所有组件,让开发者能够快速上手。
什么是cann-sdk
cann-sdk是CANN的软件开发工具包,包含:
- 开发工具链
- 运行时库
- 示例代码
- 完整文档
简单说,就是NPU开发的"全家桶"。
SDK整体工作流程
SDK组成
1. 核心组件
cann-sdk核心组件: ┌─────────────────────────────────────────┐ │ 开发工具 │ │ ┌─────────┬─────────┬─────────┐ │ │ │ 编译器 │ 调试器 │ 性能分析│ │ │ └─────────┴─────────┴─────────┘ │ ├─────────────────────────────────────────┤ │ 运行时库 │ │ ┌─────────┬─────────┬─────────┐ │ │ │ Runtime │ HCCL │ TBE │ │ │ └─────────┴─────────┴─────────┘ │ ├─────────────────────────────────────────┤ │ 算子库 │ │ ┌─────────┬─────────┬─────────┐ │ │ │ ops-nn │ ops-cv │ ops-data│ │ │ └─────────┴─────────┴─────────┘ │ ├─────────────────────────────────────────┤ │ 示例和文档 │ │ ┌─────────┬─────────┬─────────┐ │ │ │ 示例代码│ 教程 │ API文档 │ │ │ └─────────┴─────────┴─────────┘ │ └─────────────────────────────────────────┘2. 项目结构
cann-sdk/ ├── bin/ # 可执行文件 │ ├── atc # 模型转换工具 │ ├── msame # 模型推理工具 │ └── npu-smi # NPU监控工具 ├── include/ # 头文件 │ ├── acl/ # ACL头文件 │ ├── hccl/ # HCCL头文件 │ └── tbe/ # TBE头文件 ├── lib/ # 库文件 │ ├── libascendcl.so # ACL库 │ ├── libhccl.so # HCCL库 │ └── libtege.so # TBE库 ├── tools/ # 开发工具 │ ├── cmake/ # CMake工具 │ ├── python/ # Python工具 │ └── profiler/ # 性能分析工具 ├── samples/ # 示例代码 │ ├── cpp/ # C++示例 │ ├── python/ # Python示例 │ └── models/ # 模型示例 ├── docs/ # 文档 │ ├── api/ # API文档 │ ├── guide/ # 开发指南 │ └── tutorial/ # 教程 └── tests/ # 测试用例 ├── unit/ # 单元测试 └── integration/ # 集成测试安装配置
1. 环境要求
系统要求: - OS: Ubuntu 18.04/20.04/22.04, CentOS 7/8, EulerOS - CPU: x86_64或ARM64 - Python: 3.7+ - GCC: 7.3+ (x86_64), 7.5+ (ARM64) 硬件要求: - 昇腾NPU: Ascend310/310P/910等 - 驱动: 23.0.3及以上版本 - 固件: 23.0.3及以上版本2. 安装步骤
# 1. 下载SDKwgethttps://obs-ascend.obs.cn-east-2.myhuaweicloud.com/CANN/latest/cann-sdk.tar.gz# 2. 解压tar-zxvf cann-sdk.tar.gzcdcann-sdk# 3. 安装./install.sh --install-path=/usr/local/Ascend# 4. 配置环境变量exportASCEND_HOME=/usr/local/AscendexportLD_LIBRARY_PATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/lib64:$LD_LIBRARY_PATHexportPATH=$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/cmake/bin:$PATH# 5. 验证安装atc --version msame --version核心工具
1. ATC(Ascend Tensor Compiler)
# ATC模型转换 atc --model=model.onnx \ --framework=5 \ --output=model \ --soc_version=Ascend310P3 \ --input_format=NCHW \ --input_shape="input:1,3,224,224" # 参数说明: # --model: 输入模型路径 # --framework: 框架类型(5=ONNX) # --output: 输出模型名 # --soc_version: NPU型号 # --input_format: 输入格式 # --input_shape: 输入形状2. msame(Model Accuracy and Statistics Engine)
# msame模型推理 msame --model=model.om \ --input=input_data.bin \ --output=output_dir \ --outfmt=bin # 参数说明: # --model: 模型路径 # --input: 输入数据路径 # --output: 输出目录 # --outfmt: 输出格式(bin/text)3. npu-smi(NPU System Management Interface)
# npu-smi监控 npu-smi info # 查看NPU信息 npu-smi health # 健康检查 npu-smi ttop # 任务监控 npu-smi set -t 30 # 设置功耗上限30W开发流程
1. 模型开发流程
模型开发流程: 训练 → 导出 → 转换 → 部署 → 推理 ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │训练 │ → │导出 │ → │转换 │ → │部署 │ → │推理 │ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ ↓ ↓ ↓ ↓ ONNX/ ATC Runtime 应用 SavedModel .om 部署2. 完整开发示例
# 1. 训练模型(PyTorch)python train.py --output_dir=./models# 2. 导出为ONNXpython export.py --model=./models/best.pth --output=./models/model.onnx# 3. 使用ATC转换模型atc --model=./models/model.onnx\--framework=5\--output=./models/model\--soc_version=Ascend310P3\--input_format=NCHW\--input_shape="input:1,3,224,224"# 4. 准备输入数据python prepare_input.py --output=./input_data.bin# 5. 使用msame推理msame --model=./models/model.om\--input=./input_data.bin\--output=./output\--outfmt=bin# 6. 后处理结果python postprocess.py --input=./outputC++开发
1. 环境配置
# CMakeLists.txt cmake_minimum_required(VERSION 3.10) project(npu_application) # 设置CANN路径 set(ASCEND_HOME "/usr/local/Ascend") set(ASCEND_HOME ${ASCEND_HOME} CACHE PATH "Ascend Home Directory") # 设置C++标准 set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 查找ACL库 find_path(ACL_INCLUDE_DIR NAMES acl/acl.h PATHS ${ASCEND_HOME}/ascend-toolkit/latest/fwkacllib/include NO_DEFAULT_PATH ) find_library(ACL_LIB NAMES ascendcl PATHS ${ASCEND_HOME}/ascend-toolkit/latest/fwkacllib/lib64 NO_DEFAULT_PATH ) # 包含目录 include_directories( ${ACL_INCLUDE_DIR} ) # 链接库 link_directories( ${ASCEND_HOME}/ascend-toolkit/latest/fwkacllib/lib64 ) # 添加可执行文件 add_executable(npu_app main.cpp) target_link_libraries(npu_app ${ACL_LIB})2. ACL编程
// main.cpp#include<iostream>#include"acl/acl.h"intmain(){// 初始化ACLconstchar*aclConfigPath="";aclError ret=aclInit(aclConfigPath);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclInit failed: "<<ret<<std::endl;return-1;}// 设置设备ret=aclrtSetDevice(0);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclrtSetDevice failed: "<<ret<<std::endl;aclFinalize();return-1;}// 加载模型constchar*modelPath="./model.om";uint32_tmodelId;ret=aclmdlLoadFromFile(modelPath,&modelId);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclmdlLoadFromFile failed: "<<ret<<std::endl;aclrtResetDevice(0);aclFinalize();return-1;}// 创建模型描述aclmdlDesc*modelDesc;ret=aclmdlCreateDesc(&modelDesc);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclmdlCreateDesc failed: "<<ret<<std::endl;aclmdlUnload(modelId);aclrtResetDevice(0);aclFinalize();return-1;}ret=aclmdlGetDesc(modelDesc,modelId);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclmdlGetDesc failed: "<<ret<<std::endl;aclmdlDestroyDesc(modelDesc);aclmdlUnload(modelId);aclrtResetDevice(0);aclFinalize();return-1;}// 准备输入size_t inputSize=3*224*224*sizeof(float);void*inputBuffer=nullptr;ret=aclrtMalloc(&inputBuffer,inputSize,ACL_MEM_MALLOC_HUGE_FIRST);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclrtMalloc failed: "<<ret<<std::endl;// 清理资源...return-1;}// 拷贝输入数据float*inputData=reinterpret_cast<float*>(inputBuffer);// ...填充inputData...// 准备输出size_t outputSize=1000*sizeof(float);void*outputBuffer=nullptr;ret=aclrtMalloc(&outputBuffer,outputSize,ACL_MEM_MALLOC_HUGE_FIRST);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclrtMalloc failed: "<<ret<<std::endl;// 清理资源...return-1;}// 创建输入datasetaclmdlDataset*inputDataset=aclmdlCreateDataset();aclDataBuffer*inputDataBuffer=aclCreateDataBuffer(inputBuffer,inputSize);aclmdlAddDatasetBuffer(inputDataset,inputDataBuffer);// 创建输出datasetaclmdlDataset*outputDataset=aclmdlCreateDataset();aclDataBuffer*outputDataBuffer=aclCreateDataBuffer(outputBuffer,outputSize);aclmdlAddDatasetBuffer(outputDataset,outputDataBuffer);// 执行推理ret=aclmdlExecute(modelId,inputDataset,outputDataset);if(ret!=ACL_ERROR_NONE){std::cerr<<"aclmdlExecute failed: "<<ret<<std::endl;// 清理资源...return-1;}// 获取输出结果float*outputData=reinterpret_cast<float*>(outputBuffer);// ...处理outputData...// 清理资源aclmdlDestroyDataset(inputDataset);aclmdlDestroyDataset(outputDataset);aclrtFree(inputBuffer);aclrtFree(outputBuffer);aclmdlDestroyDesc(modelDesc);aclmdlUnload(modelId);aclrtResetDevice(0);aclFinalize();std::cout<<"Inference completed successfully"<<std::endl;return0;}Python开发
1. 安装Python库
# 安装Python ACL库cd$ASCEND_HOME/ascend-toolkit/latest/fwkacllib/python/site-packages pipinstallacl-*.whl2. ACL Python编程
# acl_python_example.pyimportaclimportnumpyasnpdefmain():# 初始化ACLret=acl.init()ifret!=0:print(f"acl.init failed:{ret}")return-1# 设置设备ret=acl.rt.set_device(0)ifret!=0:print(f"acl.rt.set_device failed:{ret}")acl.finalize()return-1# 加载模型model_path="./model.om"model_id,ret=acl.mdl.load_from_file(model_path)ifret!=0:print(f"acl.mdl.load_from_file failed:{ret}")acl.rt.reset_device(0)acl.finalize()return-1# 创建模型描述model_desc=acl.mdl.create_desc()ret=acl.mdl.get_desc(model_desc,model_id)ifret!=0:print(f"acl.mdl.get_desc failed:{ret}")acl.mdl.unload(model_id)acl.rt.reset_device(0)acl.finalize()return-1# 准备输入input_size=3*224*224input_data=np.random.randn(1,3,224,224).astype(np.float32)# 分配输入内存input_buffer,ret=acl.rt.malloc(input_size*4)ifret!=0:print(f"acl.rt.malloc failed:{ret}")# 清理资源...return-1# 拷贝输入数据ret=acl.rt.memcpy(input_buffer,input_data.tobytes(),input_size*4)ifret!=0:print(f"acl.rt.memcpy failed:{ret}")# 清理资源...return-1# 准备输出output_size=1000output_buffer,ret=acl.rt.malloc(output_size*4)ifret!=0:print(f"acl.rt.malloc failed:{ret}")# 清理资源...return-1# 创建输入datasetinput_dataset=acl.mdl.create_dataset()input_data_buffer=acl.create_data_buffer(input_buffer,input_size*4)acl.mdl.add_dataset_buffer(input_dataset,input_data_buffer)# 创建输出datasetoutput_dataset=acl.mdl.create_dataset()output_data_buffer=acl.create_data_buffer(output_buffer,output_size*4)acl.mdl.add_dataset_buffer(output_dataset,output_data_buffer)# 执行推理ret=acl.mdl.execute(model_id,input_dataset,output_dataset)ifret!=0:print(f"acl.mdl.execute failed:{ret}")# 清理资源...return-1# 获取输出结果output_ptr=acl.get_data_buffer_addr(output_data_buffer)output_size=acl.get_data_buffer_size(output_data_buffer)output_data=acl.util.ptr_to_bytes(output_ptr,output_size)output_array=np.frombuffer(output_data,dtype=np.float32)# 打印结果print("Output shape:",output_array.shape)print("Top 5 predictions:")top5_indices=output_array.argsort()[-5:][::-1]foridxintop5_indices:print(f" Index{idx}:{output_array[idx]:.4f}")# 清理资源acl.mdl.destroy_dataset(input_dataset)acl.mdl.destroy_dataset(output_dataset)acl.rt.free(input_buffer)acl.rt.free(output_buffer)acl.mdl.destroy_desc(model_desc)acl.mdl.unload(model_id)acl.rt.reset_device(0)acl.finalize()print("Inference completed successfully")return0if__name__=="__main__":main()性能优化
1. 内存池
// 使用内存池aclrtMemPool memoryPool;aclError ret=aclrtMemPoolCreate(&memoryPool,ACL_MEM_MALLOC_HUGE_FIRST);// 从内存池分配void*buffer;ret=aclrtMallocFromMemPool(&buffer,memoryPool,size);// 释放回内存池ret=aclrtFreeMemPool(buffer);// 销毁内存池ret=aclrtMemPoolDestroy(memoryPool);2. 流处理
// 使用流处理aclrtStream stream;aclError ret=aclrtCreateStream(&stream);// 异步操作ret=aclrtMemcpyAsync(dst,dstSize,src,srcSize,ACL_MEMCPY_DEVICE_TO_DEVICE,stream);// 同步流ret=aclrtSynchronizeStream(stream);// 销毁流ret=aclrtDestroyStream(stream);调试技巧
1. 错误处理
// 错误处理宏#defineCHECK_ACL(ret,msg)\do{\if((ret)!=ACL_ERROR_NONE){\std::cerr<<msg<<" failed: "<<(ret)<<std::endl;\return-1;\}\}while(0)// 使用aclError ret=aclInit("");CHECK_ACL(ret,"aclInit");2. 日志输出
// 设置日志级别aclError ret=aclmdlSetLogConfig("log.config");// 自定义日志输出aclError ret=aclmdlSetLogLevel("log",0);// 0=debug, 1=info, 2=warning, 3=error常见问题
Q1:SDK支持哪些操作系统?
Ubuntu 18.04/20.04/22.04、CentOS 7/8、EulerOS等主流Linux发行版。
Q2:如何升级SDK?
卸载旧版本,安装新版本。确保驱动版本匹配。
Q3:SDK占用多少磁盘空间?
约5-10GB,取决于安装的组件。
总结
cann-sdk是CANN的软件开发工具包,主要特点:
- 完整的开发工具链
- 丰富的运行时库
- 大量示例代码
- 详尽的文档
对于基于CANN开发NPU应用,cann-sdk是必备的工具包。
相关链接
- cann-sdk仓库:https://atomgit.com/cann/cann-sdk
- CANN仓库:https://atomgit.com/cann
- Runtime:https://atomgit.com/cann/runtime
本文基于cann-sdk仓库公开信息撰写,如有错误欢迎指正。