学习昇腾开发的第11天--主要接口调用流程
一、主要接口调用流程:
二、运行管理资源Device、Context、Stream基本关系:
1)Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。不同Context的Stream、不同Context的Event是完全隔离的,无法建立同步等待关系
2)Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。
3)Event支持调用AscendCL接口同步Stream之间的任务,包括同步Host与Device之间的任务、Device与Device间的任务。
总结:一般情况下单线程多Stream性能更优。
三、VDEC视频解码
四、ATB加速库接口
- CANN版本≥8.0.0且MindIE版本≥1.0.0时,直接使用MindIE的推理引擎调用ATB加速库。在需要回退CANN版本时,回退后的CANN版本不能<8.0.0。
- CANN版本<8.0.0或MindIE版本<1.0.0时,在需要升级或者回退CANN版本时,请基于目标CANN版本重新编译调用ATB的程序,才能正常使用ATB加速库。
由于我的cann是7.0.0RC1版本,无法使用ATB,所以需要升级CANN。
在资源下载中心社区版,重新去下载CANN包和MindIE包。
升级步骤参考:
升级CANN-CANN商用版8.1.RC1-昇腾社区
注意:升级驱动一定要查看版本是否适配(一般适配就近版本)
如果固件、驱动、toolkit、kernels版本配套,可以直接单独升级CANN,如果不配套就升级,大概率会升级失败,此时最好选择升级的路径是:固件-->驱动-->CANN
注意!:如果升级固件失败,可能是固件包不匹配
解决方法:不升级固件驱动包,选择版本稍低一点的cann(toolkit和kernels两个包)
注意!:如果CANN还是升级失败就选择install的方式安装
eg:./Ascend-cann-kernels-<chip_type>_<version>_linux-<arch>.run --install
五、调用ACL接口有对应链接但找不到函数实现问题
具体报错:
通过查询官方文档,从acl v1.2.0起所有新版本的acl不再支持这两个api,意思就是这连各国api已经被废弃了!!!部分api有新的替代api,当然目前还没看到这两个错误信息的替代api。
可以通过代码来判断当前ACL版本:
int32_t major = 0, minor = 0, patch = 0;
aclError ret = aclrtGetVersion(&major, &minor, &patch);if (ret == ACL_SUCCESS) {std::cout << "AscendCL Version: " << major << "." << minor << "." << patch << std::endl;
} else {std::cerr << "Failed to get AscendCL version, error code: " << ret << std::endl;
}
代码实现(目前实现部分后续补充):
1、ACL初始化
// 初始化aclaclError acl_Init_ret =aclInit(NULL);if (acl_Init_ret != ACL_SUCCESS) {qDebug() << "Failed to Init ACL, error:" << acl_Init_ret;}else qDebug()<<"sucssce:"<<acl_Init_ret;
2、运行管理资源申请
//获取可用Device的数量uint32_t deviceCount = 0; // 定义一个变量接收设备数量aclError acl_deviceCount_ret = aclrtGetDeviceCount(&deviceCount);if (acl_deviceCount_ret == ACL_SUCCESS) {qDebug() <<"sucssce:"<<acl_deviceCount_ret<< "Device count:" << deviceCount;} else {qDebug() << "Failed to get device count, error:" << acl_deviceCount_ret;}// 设置使用设备0aclError acl_SetDevice_ret = aclrtSetDevice(0);if (acl_SetDevice_ret != ACL_SUCCESS) {qDebug() << "Failed to set device, error:" << acl_SetDevice_ret;}else qDebug()<<"sucssce:"<<acl_SetDevice_ret;//显示创建ContextaclrtContext myContext0;aclError acl_CreateContext_ret = aclrtCreateContext(&myContext0,0);if(acl_CreateContext_ret != ACL_SUCCESS){qDebug() << "Failed to Create Context, error:" << acl_CreateContext_ret;}else qDebug()<<"sucssce:"<<acl_CreateContext_ret;//显示创建StreamaclrtStream myStream0;aclError acl_CreateStream_ret = aclrtCreateStream(&myStream0);if(acl_CreateStream_ret != ACL_SUCCESS){qDebug() << "Failed to Create Context, error:" << acl_CreateStream_ret;}else qDebug()<<"sucssce:"<<acl_CreateStream_ret;
3、创建一个C++线程
4、实现回调函数
void Utils:: callback(acldvppStreamDesc *input, acldvppPicDesc *output, void *userdata)
{Utils utilsobj;static int count = 1;if (output != nullptr) {//获取VDEC解码的输出内存,调用自定义函数WriteToFile将输出内存中的数据写入文件后,再调用acldvppFree接口释放输出内存void *vdecOutBufferDev = acldvppGetPicDescData(output);if (vdecOutBufferDev != nullptr) {// 0: vdec success; others, vdec failed//retCode为0表示解码成功,为1表示解码失败。如果解码失败,需要根据日志中的返回码判断具体的问题,返回码请参见返回码说明。int retCode = acldvppGetPicDescRetCode(output);if (retCode == 0) {// process task: write fileuint32_t size = acldvppGetPicDescSize(output);std::string fileNameSave = "outdir/image" + std::to_string(count);// vdec输出结果在device侧,在WriteToFile方法中进行下述处理if (!utilsobj.WriteToFile(fileNameSave.c_str(), vdecOutBufferDev, size)) {ERROR_LOG("write file failed.");}} else {ERROR_LOG("vdec decode frame failed.");}// free output vdecOutBufferDevaclError ret = acldvppFree(vdecOutBufferDev);}// 释放acldvppPicDesc类型的数据,表示解码后输出图片描述数据aclError ret = acldvppDestroyPicDesc(output);}// free input vdecInBufferDev and destroy stream descif (input != nullptr) {void *vdecInBufferDev = acldvppGetStreamDescData(input);if (vdecInBufferDev != nullptr) {aclError ret = acldvppFree(vdecInBufferDev);}// 释放acldvppStreamDesc类型的数据,表示解码的输入码流描述数据aclError ret = acldvppDestroyStreamDesc(input);}INFO_LOG("success to callback %d.", count);count++;
}