一、主要接口调用流程:

二、运行管理资源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初始化

// 初始化acl
    aclError 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;
    }

    // 设置使用设备0
    aclError 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;

    //显示创建Context
    aclrtContext 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;

    //显示创建Stream
    aclrtStream 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 file
               uint32_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 vdecOutBufferDev
           aclError ret = acldvppFree(vdecOutBufferDev);
       }
       // 释放acldvppPicDesc类型的数据,表示解码后输出图片描述数据
       aclError ret = acldvppDestroyPicDesc(output);
   }

   // free input vdecInBufferDev and destroy stream desc
   if (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++;
}

Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐