下载
中文
注册

推理结果处理

基本原理

关于模型执行的输出数据,如需进行进一步的处理,可由用户自行管理实现逻辑。

示例代码(直接处理内存中的数据)

以图片分类网络为例,模型执行结束后,需处理每一张图片的模型推理结果,直接输出top5置信度的类别编号。您可以从样例介绍中获取完整样例代码。

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

//处理模型推理的输出数据,输出top5置信度的类别编号 
//output_表示模型执行的输出
for (size_t i = 0; i < aclmdlGetDatasetNumBuffers(output_); ++i) {
    //获取每个输出的内存地址和内存大小
    aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(output_, i);
    void* data = aclGetDataBufferAddr(dataBuffer);

    size_t len = aclGetDataBufferSizeV2(dataBuffer);

    //将内存中的数据转换为float类型
    float *outData = NULL;
    outData = reinterpret_cast<float*>(data);
        
    //屏显每张图片的top5置信度的类别编号
    map<float, int, greater<float> > resultMap;
    for (int j = 0; j < len / sizeof(float); ++j) {
        resultMap[*outData] = j;
        outData++;
    }
    int cnt = 0;
    for (auto it = resultMap.begin(); it != resultMap.end(); ++it) {
        // print top 5
        if (++cnt > 5) {
            break;
        }

        INFO_LOG("top %d: index[%d] value[%lf]", cnt, it->second, it->first);
}

示例代码(调用单算子处理推理结果)

以图片分类网络为例,模型执行结束后,需处理每一张图片的模型推理结果,直接输出最大置信度的类别编号。您可以从样例介绍中获取完整样例代码。

当前示例中,使用Cast算子(将推理结果的数据类型从float32转成float16)和ArgMaxD算子(从推理结果中查找最大置信度的类别标识)实现数据后处理。单算子调用的流程请参见算子调用,详细描述请参见单算子调用

  • Cast算子被封装成AscendCL接口,因此在使用时,将算子的输入输出Tensor描述、算子输入输出数据的内存等信息作为aclopCast的入参,直接调用aclopCast接口加载并执行算子。
  • ArgMaxD算子没有被封装成AscendCL接口,因此在使用时,必须自行构造算子描述信息(输入输出Tensor描述、算子属性等)、申请存放算子输入输出数据的内存、明确算子类型名称、调用aclopExecuteV2接口加载并执行算子。

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//提前将Cast和ArgMaxD两个单算子的定义文件*.json编译成适配昇腾AI处理器的离线模型(*.om文件),用于验证单算子的运行
//设置单算子模型文件所在的目录,加载单算子模型
//该目录相对可执行文件所在的目录,例如,编译出来的可执行文件存放在out目录下,此处就表示out/op_models目录
aclError ret1 = aclopSetModelDir("op_models");
//......

//以下步骤需针对每一张图片的模型推理结果进行处理
//1. 在数据后处理前,先获取模型推理的输出,modelOutput表示模型推理的输出
aclDataBuffer inputBuffer_[0] = aclmdlGetDatasetBuffer(modelOutput, 0);

//2. 自定义函数RunSigleOpCast,构造Cast算子的输入输出Tensor描述、申请存放算子输出数据的内存devBufferCast_、调用aclopCast接口加载并执行算子
Result ret = RunSigleOpCast();

//3. 自定义函数RunSigleOpArgMaxD,构造ArgMaxD算子的输入输出Tensor、输入输出Tensor描述、算子属性、申请存放算子输出数据的内存devBufferArgMaxD_、调用aclopExecuteV2接口加载并执行算子
ret = RunSigleOpArgMaxD();

//4.传输ArgMaxD算子的输出数据
//4.1 根据ArgMaxD算子输出数据的大小,申请内存    
void* hostBuffer = nullptr;
aclError ret = aclrtMallocHost(&hostBuffer, tensorSizeArgMaxD_);

//4.2 将ArgMaxD算子的输出数据从Device复制到Host
ret = aclrtMemcpy(hostBuffer, tensorSizeArgMaxD_, devBufferArgMaxD_, tensorSizeArgMaxD_, ACL_MEMCPY_DEVICE_TO_HOST);

//4.3 在终端窗口显示最大置信度的类别编号
int32_t* index = static_cast<int32_t*>(hostBuffer);
INFO_LOG("---> index of classification result is %d", *index);
    
//5 释放资源
//5.1 释放内存
aclrtFreeHost(hostBuffer);

//5.2 释放Device上存放算子输出数据的内存
(void)aclrtFree(devBufferCast_);
(void)aclrtFree(devBufferArgMaxD_);

//5.3 释放aclDataBuffer类型数据(用于描述算子输出数据)
(void)aclDestroyDataBuffer(outputBufferCast_[0]);
(void)aclDestroyDataBuffer(outputBufferArgMaxD_[0]);
//......