OpenCV目前通过调用CANN提供的接口的方式调用NPU,其中调用的接口主要包括数据内存的申请、拷贝和释放、算子执行。
了解CANN
CANN的官方介绍:
CANN(Compute Architecture for Neural Networks)是华为针对AI场景推出的异构计算架构,对上支持多种AI框架,对下服务AI处理器与编程,发挥承上启下的关键作用,是提升昇腾AI处理器计算效率的关键平台。同时针对多样化应用场景,提供高效易用的编程接口,支持用户快速构建基于昇腾平台的AI应用和业务。
CANN中面向开发者的即为AscendCL,开发者通过AscendC编程,而CANN则根据编译后的指令通过任务调度将任务下发给不同的处理单元,通过驱动完成对计算资源的调用。这里计算资源主要指AI Core和AI CPU,根据处理数据的不同,即AI Core负责矩阵、向量、标量计算密集的算子计算,而AI CPU则负责非矩阵类、逻辑复杂的分支密集型计算,目前,AI Core还承担了部分无法执行在AI Core的计算密集算子计算。
OpenCV昇腾算子开发
CANN主要的功能特性包括推理应用开发、模型训练和算子开发,OpenCV昇腾算子的开发目前属于推理应用开发,后续提升算子支持完整度过程中会加入自定义算子开发。
开发流程
CANN应用开发基于AscendCL实现,因此应用开发的基础是掌握AscendCL的架构及基本概念和接口的典型调用流程。本篇主要集中于算子调用流程,媒体数据处理的详细解析见dvpp接口调用。
常用接口
在OpenCV应用开发中,常用的算子包括ACL(去)初始化接口、设备设置接口、device内存操作接口、Stream管理接口和具体的算子接口。ACL(去)初始化接口用来初始化系统内部资源;设备设置接口用来获取device信息、指定或切换device等;device内存操作口用来实现device和host侧的数据搬移;Stream管理接口用来管理任务的并行,一个Stream内部的任务保序执行,即Stream根据发送过来的任务依次执行;不同Stream中的任务并行执行。具体的算子接口则实现具体的计算功能。
下面表格中为除具体算子接口外的常用接口列表,其详细用法参见昇腾文档。
算子类别 | 接口名称 | 功能 |
---|---|---|
ACL(去)初始化接口 | aclInit(const char *configPath) | 初始化ACL系统,用在程序开始时 |
aclFinalize() | 去初始化ACL系统,用在程序退出时 | |
设备设置接口 | aclrtGetDevice(int32_t *deviceId) | 获取当前线程的目标设备ID |
aclrtResetDevice(int32_t deviceId) | 重置当前操作的设备并释放设备资源 | |
aclrtGetDeviceCount(uint32_t *count) | 获取设备数量 | |
device内存操作接口 | aclrtMalloc(void **devPtr,size_t size,aclrtMemMallocPolicy policy) | 申请设备内存(真实申请的内存是32bytes对齐的) |
aclrtFree(void *devPtr) | 释放设备内存 | |
aclrtMemcpy(void *dst, size_t destMax, const void *src,size_t count,aclrtMemcpyKind kind) | HOST和DEVICE之间的同步内存复制 | |
aclrtMemcpyAsync(void *dst, size_t destMax,const void *src,size_t count, aclrtMemcpyKind kind, aclrtStream stream) | HOST和DEVICE之间的异步内存复制 | |
aclrtMemcpy2d(void *dst,size_t dpitch,const void *src, size_t spitch,size_t width,size_t height,aclrtMemcpyKind kind) | HOST和DEVICE之间二维矩阵的同步内存复制 | |
aclrtMemcpy2dAsync(void *dst,size_t dpitch,const void *src, size_t spitch,size_t width,size_t height,aclrtMemcpyKind kind,aclrtStream stream) | HOST和DEVICE之间二维矩阵的异步内存复制 | |
aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count) | 同步内存初始化 | |
aclrtMemsetAsync(void *devPtr,size_t maxCount,int32_t value, size_t count,aclrtStream stream) | 异步内存初始化 | |
Stream管理接口 | aclrtCreateStream(aclrtStream *stream) | 创建一个Stream |
aclrtSynchronizeStream(aclrtStream stream) | 阻塞应用程序运行,直到指定Stream中的所有任务都完成 |
QA
如何确定算子执行在AI Core还是AI CPU?
- 查看CANN算子清单
- 算子清单由于更新迭代问题不一定最准确,此时可以查看
~/Ascend/ascend-toolkit/XXX(CANN版本号)/opp/built-in/op_impl/ai_core/tbe/config/ascendXXX(NPU型号)
下的json文件,查看当前设备支持的AI Core算子清单;相应地,AI CPU的则位于/usr/local/Ascend/ascend-toolkit/XXX(CANN版本号)/opp/built-in/op_impl/aicpu/aicpu_kernel/config
如何打印详细日志?
1 | # 设置全局日志级别(0:DEBUG;1:INFO; 2:WARNING; 3:ERROR; 4:NULL(不输出)) |