图编译和图执行
=======

单算子模型执行是指基于图IR执行算子，先编译算子（例如，使用OMG工具将Ascend IR定义的单算子描述文件编译成算子omc模型文件），再调用模型加载推理接口执行单算子网络。下文仅提供单算子模型执行的样例和基础内容讲解，详细内容请参考[端侧部署](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-whole-deployment-process)章节。

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/74/v3/anPaovxiTW28L1ThOj0SYw/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073700Z&HW-CC-Expire=86400&HW-CC-Sign=B112200F9B6479A1D15EB1262CEABE727C9D23BBC21E3F148BA1043FAF2308C7)

HarmonyOS Next暂不支持图编译与图执行，仅支持通过[AI框架算子适配](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-overview-of-ai-framework-operator)方式集成自定义算子，以下步骤仅供参考。

#### 环境要求

*   已参考[环境准备](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-environment-preparation)，完成DDK驱动和软件的安装，配置DDK软件所需基本环境变量。
    
    安装DDK软件后，使用DDK运行开发者进行编译、运行时，需要以DDK运行开发者登录环境，执行**source ${install\_path}/ddk/tools/tools\_ascendc/set\_ascendc\_env.sh**命令设置环境变量。其中${install\_path}为DDK软件的安装目录，例如：/home。
    
*   已参考完成算子的开发和部署。
    

#### 准备验证代码工程

在执行NPU调试命令时，例如：

ascendebug kernel --backend npu  --chip-version kirin9020 --repo-type customize --json-file ./temp.json --core-type AiCore

命令行参数详见[NPU调测参数](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/cannkit-cli-parameters#npu调测参数)，会在${debug\_workspace} /${op\_type} /npu/src下生成验证样例工程，代码工程目录结构如下。

src
├── BuildIRGraph.cpp // 生成单算子图源文件
├── BuildIRGraph.h // 单算子图入口：CreateCustomIRGraph
├── build.sh // omc 模型编译脚本
├── CMakeLists.txt
├── custom\_graph.omc // 编译后得到的omc模型
└── op\_proto.h // 算子编译输出的算子原型定义头文件

#### 生成单算子离线模型文件

执行验证样例工程下的build.sh。

./build.sh

以上命令执行后，会在当前路径下生成custom\_graph.omc的离线模型文件。

#### 生成输入数据

在样例工程目录下，执行如下命令：

python3 scripts/gen\_data.py

会在input目录下生成两个shape为(8,2048)，数据类型为float16的数据文件input\_0.bin与input\_1.bin，用于进行AddCustom算子的验证。

代码样例如下。

import numpy as np
a = np.random.randint(100, size=(8, 2048,)).astype(np.float16)
b = np.random.randint(100, size=(8, 2048,)).astype(np.float16)
a.tofile('input\_0.bin')
b.tofile('input\_1.bin')

#### APP集成代码

开发者可以参考如下样例编写模型加载、执行的代码逻辑。完整集成流程请参考[应用开发](https://developer.huawei.com/consumer/cn/doc/hiai-Guides/app-dev-0000001052605540)。

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

int RunModel(void\* modelData, size\_t modelSize)
{
    // 1.加载omc模型
    auto modelDescV1 = std::make\_shared<hiai::AiModelDescription>("model", 3, 0, 0, 0);
    modelDescV1->SetModelBuffer(modelData, modelSize);

    std::vector<std::shared\_ptr<hiai::AiModelDescription>> modelDescVec;
    modelDescVec.push\_back(modelDescV1);
    auto clientV1 = std::make\_shared<hiai::AiModelMngerClient>();
    if (clientV1->Init(nullptr) != hiai::SUCCESS) {
        LOGE("client Init() failed.");
        return FAILURE;
    }

    if (clientV1->Load(modelDescVec) != hiai::SUCCESS) {
        LOGE("client Load() failed.");
        return FAILURE;
    }
    LOGI("load model success");
    std::vector<hiai::TensorDimension> inDimVecV1;
    std::vector<hiai::TensorDimension> outDimVecV1;
    std::vector<std::shared\_ptr<hiai::AiTensor>> inTensorVecV1;
    std::vector<std::shared\_ptr<hiai::AiTensor>> outTensorVecV1;

    if (clientV1->GetModelIOTensorDim(modelDescV1->GetName(), inDimVecV1, outDimVecV1) != hiai::SUCCESS) {
        LOGE("client GetModelIOTensorDim() failed.");
        clientV1->UnLoadModel();
        return FAILURE;
    }
    // 2、设置模型输入、输出
    for (size\_t i = 0; i < INPUT\_NUM &&  i < inDimVecV1.size(); ++i) {
        void \*data = nullptr;
        size\_t size = 0;
        LOGI("open input file  inputFile: %s ", INPUT\_LIST\[i\].c\_str());
        if (!ReadData(INPUT\_LIST\[i\], &data, size)) {
            LOGE("open input file failed! inputFile: %s ", INPUT\_LIST\[i\].c\_str());
            clientV1->UnLoadModel();
            return FAILURE;
        }

        auto inputV1 = std::make\_shared<hiai::AiTensor>();

        inputV1->Init(&inDimVecV1\[i\], INPUT\_TYPE);
        if (inputV1->GetSize() != size) {
            LOGE("inputSize: %d != fileSize: %zu ", inputV1->GetSize(), size);
            clientV1->UnLoadModel();
            free(data);
            data = nullptr;
            return FAILURE;
        }
        memcpy(inputV1->GetBuffer(), data, size);
        inTensorVecV1.push\_back(inputV1);
        free(data);
        data = nullptr;
    }
    LOGI("load input success");

    for (size\_t i = 0; i < outDimVecV1.size(); i++) {
        auto outputV1 = std::make\_shared<hiai::AiTensor>();
        outputV1->Init(&outDimVecV1\[i\], OUTPUT\_TYPE);
        outTensorVecV1.push\_back(outputV1);
    }
    LOGI("init output success");

    // 3、进行模型推理
    hiai::AiContext context;
    context.AddPara("model\_name", "model");
    int32\_t istamp = 0;

    auto retCode = clientV1->Process(context, inTensorVecV1, outTensorVecV1, 1000, istamp);
    if (retCode != hiai::SUCCESS) {
        LOGE("process failed.");
        clientV1->UnLoadModel();
        return retCode;
    }
    LOGI("process success");

    for (size\_t i = 0; i < outTensorVecV1.size(); i++) {
        char\* data = reinterpret\_cast<char\*>(outTensorVecV1\[i\]->GetBuffer());
        DumpBufferToFile(data, outTensorVecV1\[i\]->GetSize(), OUTPUT\_PATH);
    }
    LOGI("dump output success");

    // 4、模型卸载
    clientV1->UnLoadModel();
    return retCode;
}