112e714ceSopenharmony_ci# Neural Network Runtime设备接入指导 212e714ceSopenharmony_ci 312e714ceSopenharmony_ci## 概述 412e714ceSopenharmony_ci 512e714ceSopenharmony_ci### 功能简介 612e714ceSopenharmony_ci 712e714ceSopenharmony_ciNNRt(Neural Network Runtime,神经网络运行时)是面向AI领域的跨芯片推理计算运行时,作为中间桥梁连通上层AI推理框架和底层加速芯片,实现AI模型的跨芯片推理计算。 812e714ceSopenharmony_ci 912e714ceSopenharmony_ciNNRt开放了设备接口,芯片厂商通过设备接口将专有加速芯片接入NNRt,从而实现与OpenHarmony社区生态的对接。以下内容将介绍芯片如何接入NNRt。 1012e714ceSopenharmony_ci 1112e714ceSopenharmony_ci### 基本概念 1212e714ceSopenharmony_ci在开发前,开发者需要先了解以下概念,以便更好地理解全文内容: 1312e714ceSopenharmony_ci 1412e714ceSopenharmony_ci- HDI(Hardware Device Interface):OpenHarmony硬件设备接口,定义系统中跨进程通信的接口,实现服务间的跨进程通信。 1512e714ceSopenharmony_ci- IDL(Interface Description Language):接口描述语言,是HDI接口的语言格式。 1612e714ceSopenharmony_ci 1712e714ceSopenharmony_ci### 约束与限制 1812e714ceSopenharmony_ci- 系统版本:OpenHarmony主干版本。 1912e714ceSopenharmony_ci- 开发环境:Ubuntu 18.04及以上。 2012e714ceSopenharmony_ci- 接入设备:具备AI计算能力的芯片。 2112e714ceSopenharmony_ci 2212e714ceSopenharmony_ci### 运作机制 2312e714ceSopenharmony_ciNNRt通过HDI接口实现与设备芯片的对接,由HDI接口实现跨进程通信。 2412e714ceSopenharmony_ci 2512e714ceSopenharmony_ci**图1** NNRt架构图 2612e714ceSopenharmony_ci 2712e714ceSopenharmony_ci 2812e714ceSopenharmony_ci 2912e714ceSopenharmony_ci整个架构主要分为三层,AI应用在应用层,AI推理框架和NNRt在系统层,设备服务在芯片层。AI应用如果要使用AI专用加速芯片进行模型推理,需要经过AI推理框架和NNRt才能调用到底层AI专用加速芯片,NNRt就是负责适配底层各种AI专用加速芯片的中间层。NNRt开放了标准统一的HDI设备接口,众多AI专用加速芯片都可以通过HDI接口接入OpenHarmony。此外NNRt也开放了标准统一的接口对接上层各种AI推理框架。 3012e714ceSopenharmony_ci 3112e714ceSopenharmony_ci程序运行时,AI应用、AI推理框架、NNRt都运行在用户进程中,底层AI芯片设备服务运行在HDI服务进程中。NNRt根据HDI接口实现了HDI Client,服务端也需要根据HDI接口实现HDI Service,两者通过OpenHarmony标准的HDF子系统实现跨进程通信。 3212e714ceSopenharmony_ci 3312e714ceSopenharmony_ci## 开发指导 3412e714ceSopenharmony_ci 3512e714ceSopenharmony_ci### 场景介绍 3612e714ceSopenharmony_ci当需要将一款AI加速芯片接入NNRt的时候,可以参考下文。下文以RK3568芯片为例,展示RK3568 CPU如何通过NNRt的V2.0版本HDI接口接入NNRt,并完成AI模型推理。V1.0版本HDI接口接入NNRt的流程与此类似。 3712e714ceSopenharmony_ci> 依赖说明:该教程展示的RK3568 CPU接入NNRt并没有真正实现CPU的驱动,而是借用了MindSpore Lite的runtime和CPU算子,因此会依赖MindSpore Lite的动态库以及头文件。实际开发时并不需要依赖MindSpore Lite的任何库或者头文件。 3812e714ceSopenharmony_ci 3912e714ceSopenharmony_ci### 开发流程 4012e714ceSopenharmony_ciAI专用加速芯片接入NNRt的整体流程如下: 4112e714ceSopenharmony_ci 4212e714ceSopenharmony_ci**图2** AI专用加速芯片接入NNRt流程 4312e714ceSopenharmony_ci 4412e714ceSopenharmony_ci 4512e714ceSopenharmony_ci 4612e714ceSopenharmony_ci### 开发步骤 4712e714ceSopenharmony_ciAI芯片设备HDI服务开发者具体可通过以下步骤实现AI专用加速芯片对接NNRt: 4812e714ceSopenharmony_ci#### 生成HDI头文件 4912e714ceSopenharmony_ci开源社区下载OpenHarmony的代码,编译drivers_interface部件,生成HDI接口的头文件。 5012e714ceSopenharmony_ci 5112e714ceSopenharmony_ci1. [下载源码](../get-code/sourcecode-acquire.md)。 5212e714ceSopenharmony_ci 5312e714ceSopenharmony_ci2. 进入OpenHarmony源码根目录,编译NNRt的IDL接口文件(以RK3568产品为例): 5412e714ceSopenharmony_ci ```shell 5512e714ceSopenharmony_ci ./build.sh --product-name rk3568 –ccache --build-target drivers_interface_nnrt 5612e714ceSopenharmony_ci ``` 5712e714ceSopenharmony_ci 5812e714ceSopenharmony_ci 编译完成后,会在```out/rk3568/gen/drivers/interface/nnrt/v2_0```目录下生成C++类型的HDI头文件。若需要生成C类型的头文件,请在编译之前使用如下命令对```drivers/interface/nnrt/v2_0/BUILD.gn```文件中的```language```配置项进行设置。 5912e714ceSopenharmony_ci 6012e714ceSopenharmony_ci ```shell 6112e714ceSopenharmony_ci language = "c" 6212e714ceSopenharmony_ci ``` 6312e714ceSopenharmony_ci 6412e714ceSopenharmony_ci 生成头文件目录如下所示: 6512e714ceSopenharmony_ci ```text 6612e714ceSopenharmony_ci out/rk3568/gen/drivers/interface/nnrt 6712e714ceSopenharmony_ci └── v2_0 6812e714ceSopenharmony_ci ├── drivers_interface_nnrt__libnnrt_proxy_2.0_external_deps_temp.json 6912e714ceSopenharmony_ci ├── drivers_interface_nnrt__libnnrt_stub_2.0_external_deps_temp.json 7012e714ceSopenharmony_ci ├── innrt_device.h # 设备接口头文件 7112e714ceSopenharmony_ci ├── iprepared_model.h # 编译AI模型对象头文件 7212e714ceSopenharmony_ci ├── libnnrt_proxy_2.0__notice.d 7312e714ceSopenharmony_ci ├── libnnrt_stub_2.0__notice.d 7412e714ceSopenharmony_ci ├── model_types.cpp # AI模型结构定义实现文件 7512e714ceSopenharmony_ci ├── model_types.h # AI模型结构定义头文件 7612e714ceSopenharmony_ci ├── nnrt_device_driver.cpp # 设备驱动实现参考样例 7712e714ceSopenharmony_ci ├── nnrt_device_proxy.cpp 7812e714ceSopenharmony_ci ├── nnrt_device_proxy.h 7912e714ceSopenharmony_ci ├── nnrt_device_service.cpp # 设备服务端实现参考样例 8012e714ceSopenharmony_ci ├── nnrt_device_service.h # 设备服务端头文件 8112e714ceSopenharmony_ci ├── nnrt_device_stub.cpp 8212e714ceSopenharmony_ci ├── nnrt_device_stub.h 8312e714ceSopenharmony_ci ├── nnrt_types.cpp # 数据类型定义实现文件 8412e714ceSopenharmony_ci ├── nnrt_types.h # 数据类型定义头文件 8512e714ceSopenharmony_ci ├── node_attr_types.cpp # AI模型算子属性定义实现文件 8612e714ceSopenharmony_ci ├── node_attr_types.h # AI模型算子属性定义 8712e714ceSopenharmony_ci ├── prepared_model_proxy.cpp 8812e714ceSopenharmony_ci ├── prepared_model_proxy.h 8912e714ceSopenharmony_ci ├── prepared_model_service.cpp # 编译AI模型对象服务端实现参考样例 9012e714ceSopenharmony_ci ├── prepared_model_service.h # 编译AI模型对象服务端头文件 9112e714ceSopenharmony_ci ├── prepared_model_stub.cpp 9212e714ceSopenharmony_ci └── prepared_model_stub.h 9312e714ceSopenharmony_ci ``` 9412e714ceSopenharmony_ci 9512e714ceSopenharmony_ci#### 实现HDI服务 9612e714ceSopenharmony_ci 9712e714ceSopenharmony_ci1. 进入OpenHarmony源码根目录,在```drivers/peripheral```目录下新建开发目录```nnrt```,用于HDI服务开发。开发目录结构如下所示: 9812e714ceSopenharmony_ci ```text 9912e714ceSopenharmony_ci drivers/peripheral/nnrt 10012e714ceSopenharmony_ci ├── bundle.json 10112e714ceSopenharmony_ci ├── v2_0 10212e714ceSopenharmony_ci ├── BUILD.gn # 代码编译脚本文件 10312e714ceSopenharmony_ci └── hdi_cpu_service # 自定义目录 10412e714ceSopenharmony_ci ├── BUILD.gn # 代码编译脚本文件 10512e714ceSopenharmony_ci ├── include 10612e714ceSopenharmony_ci │ ├── nnrt_device_service.h # 设备服务端头文件 10712e714ceSopenharmony_ci │ ├── node_functions.h # 非必须,由具体实现决定 10812e714ceSopenharmony_ci │ ├── node_registry.h # 非必须,由具体实现决定 10912e714ceSopenharmony_ci │ └── prepared_model_service.h # 编译AI模型对象服务端头文件 11012e714ceSopenharmony_ci └── src 11112e714ceSopenharmony_ci ├── nnrt_device_driver.cpp # 设备驱动实现文件 11212e714ceSopenharmony_ci ├── nnrt_device_service.cpp # 设备服务端实现文件 11312e714ceSopenharmony_ci ├── nnrt_device_stub.cpp # 非必须,由具体实现决定 11412e714ceSopenharmony_ci ├── node_attr_types.cpp # 非必须,由具体实现决定 11512e714ceSopenharmony_ci ├── node_functions.cpp # 非必须,由具体实现决定 11612e714ceSopenharmony_ci ├── node_registry.cpp # 非必须,由具体实现决定 11712e714ceSopenharmony_ci └── prepared_model_service.cpp # 编译AI模型对象服务端实现文件 11812e714ceSopenharmony_ci ``` 11912e714ceSopenharmony_ci 12012e714ceSopenharmony_ci2. 实现设备驱动,无特殊需求可直接使用IDL文件编译生成的```nnrt_device_driver.cpp```文件,否则根据具体驱动开发。 12112e714ceSopenharmony_ci 12212e714ceSopenharmony_ci3. 实现服务接口,可参考```nnrt_device_service.cpp```和```prepared_model_service.cpp```实现文件,接口定义可以参考[NNRt的HDI接口定义](https://gitee.com/openharmony/drivers_interface/tree/master/nnrt)。 12312e714ceSopenharmony_ci 12412e714ceSopenharmony_ci4. 编译驱动和服务的实现文件为共享库。 12512e714ceSopenharmony_ci 12612e714ceSopenharmony_ci 在```drivers/peripheral/nnrt/v2_0/hdi_cpu_service/```下新建```BUILD.gn```文件,文件内容如下所示,相关参数配置内容可参考[Build教程](https://gitee.com/openharmony/build)。 12712e714ceSopenharmony_ci 12812e714ceSopenharmony_ci ```shell 12912e714ceSopenharmony_ci import("//build/ohos.gni") 13012e714ceSopenharmony_ci import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 13112e714ceSopenharmony_ci 13212e714ceSopenharmony_ci ohos_shared_library("libnnrt_service_2.0") { 13312e714ceSopenharmony_ci include_dirs = [] 13412e714ceSopenharmony_ci sources = [ 13512e714ceSopenharmony_ci "src/nnrt_device_service.cpp", 13612e714ceSopenharmony_ci "src/node_functions.cpp", 13712e714ceSopenharmony_ci "src/node_registry.cpp", 13812e714ceSopenharmony_ci "src/prepared_model_service.cpp", 13912e714ceSopenharmony_ci "src/shared_buffer_parser.cpp", 14012e714ceSopenharmony_ci "src/validation.cpp", 14112e714ceSopenharmony_ci ] 14212e714ceSopenharmony_ci 14312e714ceSopenharmony_ci external_deps = [ 14412e714ceSopenharmony_ci "c_utils:utils", 14512e714ceSopenharmony_ci "drivers_interface_nnrt:libnnrt_stub_2.0", 14612e714ceSopenharmony_ci "hdf_core:libhdf_utils", 14712e714ceSopenharmony_ci "hilog_native:libhilog", 14812e714ceSopenharmony_ci "ipc:ipc_core", 14912e714ceSopenharmony_ci ] 15012e714ceSopenharmony_ci 15112e714ceSopenharmony_ci install_images = [ chipset_base_dir ] 15212e714ceSopenharmony_ci subsystem_name = "hdf" 15312e714ceSopenharmony_ci part_name = "drivers_peripheral_nnrt" 15412e714ceSopenharmony_ci } 15512e714ceSopenharmony_ci 15612e714ceSopenharmony_ci ohos_shared_library("libnnrt_driver") { 15712e714ceSopenharmony_ci include_dirs = [] 15812e714ceSopenharmony_ci sources = [ "src/nnr_device_driver.cpp" ] 15912e714ceSopenharmony_ci deps = [ ":libnnrt_service_2.0" ] 16012e714ceSopenharmony_ci 16112e714ceSopenharmony_ci external_deps = [ 16212e714ceSopenharmony_ci "c_utils:utils", 16312e714ceSopenharmony_ci "drivers_interface_nnrt:libnnrt_stub_2.0", 16412e714ceSopenharmony_ci "hdf_core:libhdf_host", 16512e714ceSopenharmony_ci "hdf_core:libhdf_ipc_adapter", 16612e714ceSopenharmony_ci "hdf_core:libhdf_utils", 16712e714ceSopenharmony_ci "hdf_core:libhdi", 16812e714ceSopenharmony_ci "hilog_native:libhilog", 16912e714ceSopenharmony_ci "ipc:ipc_core", 17012e714ceSopenharmony_ci ] 17112e714ceSopenharmony_ci 17212e714ceSopenharmony_ci install_images = [ chipset_base_dir ] 17312e714ceSopenharmony_ci subsystem_name = "hdf" 17412e714ceSopenharmony_ci part_name = "drivers_peripheral_nnrt" 17512e714ceSopenharmony_ci } 17612e714ceSopenharmony_ci 17712e714ceSopenharmony_ci group("hdf_nnrt_service") { 17812e714ceSopenharmony_ci deps = [ 17912e714ceSopenharmony_ci ":libnnrt_driver", 18012e714ceSopenharmony_ci ":libnnrt_service_2.0", 18112e714ceSopenharmony_ci ] 18212e714ceSopenharmony_ci } 18312e714ceSopenharmony_ci ``` 18412e714ceSopenharmony_ci 18512e714ceSopenharmony_ci 将```group("hdf_nnrt_service")```添加到```drivers/peripheral/nnrt/v2_0/BUILD.gn```文件中,以便在更上目录层级就能引用。 18612e714ceSopenharmony_ci ```shell 18712e714ceSopenharmony_ci if (defined(ohos_lite)) { 18812e714ceSopenharmony_ci group("nnrt_entry") { 18912e714ceSopenharmony_ci deps = [] 19012e714ceSopenharmony_ci } 19112e714ceSopenharmony_ci } else { 19212e714ceSopenharmony_ci group("nnrt_entry") { 19312e714ceSopenharmony_ci deps = [ "./hdi_cpu_service:hdf_nnrt_service" ] 19412e714ceSopenharmony_ci } 19512e714ceSopenharmony_ci } 19612e714ceSopenharmony_ci ``` 19712e714ceSopenharmony_ci 19812e714ceSopenharmony_ci 新建```drivers/peripheral/nnrt/bundle.json```用于定义新增的```drivers_peripheral_nnrt```部件。 19912e714ceSopenharmony_ci ```json 20012e714ceSopenharmony_ci { 20112e714ceSopenharmony_ci "name": "drivers_peripheral_nnrt", 20212e714ceSopenharmony_ci "description": "Neural network runtime device driver", 20312e714ceSopenharmony_ci "version": "4.0", 20412e714ceSopenharmony_ci "license": "Apache License 2.0", 20512e714ceSopenharmony_ci "component": { 20612e714ceSopenharmony_ci "name": "drivers_peripheral_nnrt", 20712e714ceSopenharmony_ci "subsystem": "hdf", 20812e714ceSopenharmony_ci "syscap": [""], 20912e714ceSopenharmony_ci "adapter_system_type": ["standard"], 21012e714ceSopenharmony_ci "rom": "1024KB", 21112e714ceSopenharmony_ci "ram": "2048KB", 21212e714ceSopenharmony_ci "deps": { 21312e714ceSopenharmony_ci "components": [ 21412e714ceSopenharmony_ci "c_utils", 21512e714ceSopenharmony_ci "hdf_core", 21612e714ceSopenharmony_ci "hilog", 21712e714ceSopenharmony_ci "ipc", 21812e714ceSopenharmony_ci "drivers_interface_nnrt" 21912e714ceSopenharmony_ci ], 22012e714ceSopenharmony_ci "third_part": [ 22112e714ceSopenharmony_ci "bounds_checking_function" 22212e714ceSopenharmony_ci ] 22312e714ceSopenharmony_ci }, 22412e714ceSopenharmony_ci "build": { 22512e714ceSopenharmony_ci "sub_component": [ 22612e714ceSopenharmony_ci "//drivers/peripheral/nnrt/v2_0:nnrt_entry" 22712e714ceSopenharmony_ci ], 22812e714ceSopenharmony_ci "test": [ 22912e714ceSopenharmony_ci ], 23012e714ceSopenharmony_ci "inner_kits": [ 23112e714ceSopenharmony_ci ] 23212e714ceSopenharmony_ci } 23312e714ceSopenharmony_ci } 23412e714ceSopenharmony_ci } 23512e714ceSopenharmony_ci ``` 23612e714ceSopenharmony_ci 23712e714ceSopenharmony_ci#### 声明HDI服务 23812e714ceSopenharmony_ci 23912e714ceSopenharmony_ci 在对应产品的uhdf hcs配置文件中声明NNRt的用户态驱动与服务。例如针对RK3568,服务需要在```vendor/hihope/rk3568/hdf_config/uhdf/device_info.hcs```文件中新增如下配置: 24012e714ceSopenharmony_ci ```text 24112e714ceSopenharmony_ci nnrt :: host { 24212e714ceSopenharmony_ci hostName = "nnrt_host"; 24312e714ceSopenharmony_ci priority = 50; 24412e714ceSopenharmony_ci uid = ""; 24512e714ceSopenharmony_ci gid = ""; 24612e714ceSopenharmony_ci caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; 24712e714ceSopenharmony_ci nnrt_device :: device { 24812e714ceSopenharmony_ci device0 :: deviceNode { 24912e714ceSopenharmony_ci policy = 2; 25012e714ceSopenharmony_ci priority = 100; 25112e714ceSopenharmony_ci moduleName = "libnnrt_driver.z.so"; 25212e714ceSopenharmony_ci serviceName = "nnrt_device_service"; 25312e714ceSopenharmony_ci } 25412e714ceSopenharmony_ci } 25512e714ceSopenharmony_ci } 25612e714ceSopenharmony_ci ``` 25712e714ceSopenharmony_ci> 注意:修改hcs文件需要删除out目录重新编译,才能生效。 25812e714ceSopenharmony_ci 25912e714ceSopenharmony_ci#### 配置host进程用户ID和组ID 26012e714ceSopenharmony_ci 对于新增的nnrt_host进程的场景,需要配置对应进程的用户ID和组ID。 进程的用户ID在文件```base/startup/init/services/etc/passwd```中配置,进程的组ID在文件```base/startup/init/services/etc/group```中配置。 26112e714ceSopenharmony_ci ```text 26212e714ceSopenharmony_ci # 在base/startup/init/services/etc/passwd新增 26312e714ceSopenharmony_ci nnrt_host:x:3311:3311:::/bin/false 26412e714ceSopenharmony_ci 26512e714ceSopenharmony_ci # 在base/startup/init/services/etc/group新增 26612e714ceSopenharmony_ci nnrt_host:x:3311: 26712e714ceSopenharmony_ci ``` 26812e714ceSopenharmony_ci 26912e714ceSopenharmony_ci#### 配置SELinux 27012e714ceSopenharmony_ci 27112e714ceSopenharmony_ciOpenHarmony已经开启SELinux特性,需要对新增的进程和服务配置相应的SELinux规则,用于运行host进程访问某些资源、发布HDI服务等。 27212e714ceSopenharmony_ci 27312e714ceSopenharmony_ci1. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdf_service_contexts```文件中新增配置: 27412e714ceSopenharmony_ci ```text 27512e714ceSopenharmony_ci # 新增配置 27612e714ceSopenharmony_ci nnrt_device_service u:object_r:hdf_nnrt_device_service:s0 27712e714ceSopenharmony_ci ``` 27812e714ceSopenharmony_ci > ```nnrt_host```为[声明HDI服务](#声明hdi服务)步骤中配置的进程名称,下同。 27912e714ceSopenharmony_ci 28012e714ceSopenharmony_ci2. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdf_service.te```文件中新增配置: 28112e714ceSopenharmony_ci ```text 28212e714ceSopenharmony_ci # 新增配置 28312e714ceSopenharmony_ci type hdf_nnrt_device_service, hdf_service_attr; 28412e714ceSopenharmony_ci ``` 28512e714ceSopenharmony_ci 28612e714ceSopenharmony_ci3. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/hdfdomain.te```文件中新增配置: 28712e714ceSopenharmony_ci ```text 28812e714ceSopenharmony_ci # 新增配置 28912e714ceSopenharmony_ci neverallow { domain -hdfdomain -sadomain } { hdfdomain -nnrt_host -allocator_host -hdf_public_domain }:binder call; 29012e714ceSopenharmony_ci ``` 29112e714ceSopenharmony_ci 29212e714ceSopenharmony_ci4. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/public/type.te```文件中新增配置: 29312e714ceSopenharmony_ci ```text 29412e714ceSopenharmony_ci # 新增配置 29512e714ceSopenharmony_ci type nnrt_host, hdfdomain, domain; 29612e714ceSopenharmony_ci ``` 29712e714ceSopenharmony_ci 29812e714ceSopenharmony_ci5. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/vendor/hdf_devmgr.te```文件中新增配置: 29912e714ceSopenharmony_ci ```text 30012e714ceSopenharmony_ci # 新增配置 30112e714ceSopenharmony_ci allow hdf_devmgr nnrt_host:binder { call transfer }; 30212e714ceSopenharmony_ci allow hdf_devmgr nnrt_host:dir { search }; 30312e714ceSopenharmony_ci allow hdf_devmgr nnrt_host:file { open read write }; 30412e714ceSopenharmony_ci allow hdf_devmgr nnrt_host:process { getattr }; 30512e714ceSopenharmony_ci ``` 30612e714ceSopenharmony_ci 30712e714ceSopenharmony_ci6. 在```base/security/selinux/sepolicy/ohos_policy/drivers/adapter/vendor/init.te```文件中新增配置: 30812e714ceSopenharmony_ci ```text 30912e714ceSopenharmony_ci # 新增配置 31012e714ceSopenharmony_ci allow init nnrt_host:process { rlimitinh siginh transition }; 31112e714ceSopenharmony_ci ``` 31212e714ceSopenharmony_ci 31312e714ceSopenharmony_ci7. 在```base/security/selinux/sepolicy/ohos_policy/startup/init/public/chipset_init.te```文件中作如下修改: 31412e714ceSopenharmony_ci 31512e714ceSopenharmony_ci 找到chipset_init这一行: 31612e714ceSopenharmony_ci ```text 31712e714ceSopenharmony_ci allow chipset_init { light_host input_user_host wifi_host camera_host power_host audio_host }:process { rlimitinh siginh transition }; 31812e714ceSopenharmony_ci ``` 31912e714ceSopenharmony_ci 在host列表中增加nnrt_host: 32012e714ceSopenharmony_ci ```text 32112e714ceSopenharmony_ci allow chipset_init { light_host input_user_host wifi_host camera_host power_host audio_host nnrt_host }:process { rlimitinh siginh transition }; 32212e714ceSopenharmony_ci ``` 32312e714ceSopenharmony_ci 32412e714ceSopenharmony_ci8. 新建```nnrt_host.te```配置文件: 32512e714ceSopenharmony_ci ```shell 32612e714ceSopenharmony_ci # 创建nnrt文件夹 32712e714ceSopenharmony_ci mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt 32812e714ceSopenharmony_ci 32912e714ceSopenharmony_ci # 创建vendor文件夹 33012e714ceSopenharmony_ci mkdir base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor 33112e714ceSopenharmony_ci 33212e714ceSopenharmony_ci # 创建nnrt_host.te文件 33312e714ceSopenharmony_ci touch base/security/selinux/sepolicy/ohos_policy/drivers/peripheral/nnrt/vendor/nnrt_host.te 33412e714ceSopenharmony_ci ``` 33512e714ceSopenharmony_ci 33612e714ceSopenharmony_ci9. 将所需的权限写入```nnrt_host.te```文件中: 33712e714ceSopenharmony_ci ```text 33812e714ceSopenharmony_ci allow nnrt_host dev_hdf_kevent:chr_file { ioctl }; 33912e714ceSopenharmony_ci allow nnrt_host hilog_param:file { read open map }; 34012e714ceSopenharmony_ci allow nnrt_host sh:binder { transfer }; 34112e714ceSopenharmony_ci allow nnrt_host samgr:binder { call }; 34212e714ceSopenharmony_ci allow nnrt_host dev_ashmem_file:chr_file { open }; 34312e714ceSopenharmony_ci allow nnrt_host dev_unix_socket:dir { search }; 34412e714ceSopenharmony_ci allow nnrt_host hdf_device_manager:hdf_devmgr_class { get }; 34512e714ceSopenharmony_ci allow nnrt_host hdf_nnrt_device_service:hdf_devmgr_class { add get }; 34612e714ceSopenharmony_ci allow nnrt_host dev_console_file:chr_file { read write }; 34712e714ceSopenharmony_ci allow nnrt_host debug_param:file { read open map }; 34812e714ceSopenharmony_ci allow nnrt_host sa_device_service_manager:samgr_class { get }; 34912e714ceSopenharmony_ci allow nnrt_host hdf_devmgr:binder { call transfer }; 35012e714ceSopenharmony_ci allow nnrt_host hdf_nnrt_device_service:binder { call }; 35112e714ceSopenharmony_ci allow nnrt_host sysfs_devices_system_cpu:file { read open getattr }; 35212e714ceSopenharmony_ci allow sh hdf_nnrt_device_service:hdf_devmgr_class { add get }; 35312e714ceSopenharmony_ci allow sh hdf_hci_interface_service:hdf_devmgr_class { get }; 35412e714ceSopenharmony_ci allow sh nnrt_host:dir { getattr search }; 35512e714ceSopenharmony_ci allow sh nnrt_host:file { open read }; 35612e714ceSopenharmony_ci allow sh nnrt_host:process { getattr }; 35712e714ceSopenharmony_ci allow sh nnrt_host:binder { call }; 35812e714ceSopenharmony_ci allow sh nnrt_host:fd { use }; 35912e714ceSopenharmony_ci ``` 36012e714ceSopenharmony_ci 36112e714ceSopenharmony_ci10. 由于SELinux是白名单访问的权限机制,需要根据实际权限需求配置。将服务启动之后,可通过以下dmesg命令查看avc告警, 36212e714ceSopenharmony_ciavc告警会给出缺少的权限。SELinux的配置也可以参考[OpenHarmony SELinux子系统的说明](https://gitee.com/openharmony/security_selinux/blob/master/README.md)。 36312e714ceSopenharmony_ci ```shell 36412e714ceSopenharmony_ci hdc_std shell 36512e714ceSopenharmony_ci dmesg | grep nnrt 36612e714ceSopenharmony_ci ``` 36712e714ceSopenharmony_ci 36812e714ceSopenharmony_ci#### 配置部件编译入口 36912e714ceSopenharmony_ci以RK3568产品为例: 37012e714ceSopenharmony_ci```shell 37112e714ceSopenharmony_civim //productdefine/common/inherit/chipset_common.json 37212e714ceSopenharmony_ci``` 37312e714ceSopenharmony_ci在```"subsystems"```, ```"subsystem":"hdf"```, ```"components"```中添加: 37412e714ceSopenharmony_ci```shell 37512e714ceSopenharmony_ci{ 37612e714ceSopenharmony_ci "component": "drivers_peripheral_nnrt", 37712e714ceSopenharmony_ci "features": [] 37812e714ceSopenharmony_ci} 37912e714ceSopenharmony_ci``` 38012e714ceSopenharmony_ci 38112e714ceSopenharmony_ci#### 删除out目录并编译整个系统 38212e714ceSopenharmony_ci```shell 38312e714ceSopenharmony_ci# 删除out目录 38412e714ceSopenharmony_cirm -rf ./out 38512e714ceSopenharmony_ci 38612e714ceSopenharmony_ci# 编译 38712e714ceSopenharmony_ci./build.sh --product-name rk3568 –ccache --jobs=4 38812e714ceSopenharmony_ci``` 38912e714ceSopenharmony_ci 39012e714ceSopenharmony_ci 39112e714ceSopenharmony_ci### 调测验证 39212e714ceSopenharmony_ci服务开发完成后,可以使用XTS用例验证基本功能和兼容性。开发者可通过以下步骤进行验证: 39312e714ceSopenharmony_ci 39412e714ceSopenharmony_ci1. 编译NNRt的hats用例,用例在```test/xts/hats/ai/nnrt/hdi```目录下。 39512e714ceSopenharmony_ci ```shell 39612e714ceSopenharmony_ci # 进入hats目录 39712e714ceSopenharmony_ci cd test/xts/hats 39812e714ceSopenharmony_ci 39912e714ceSopenharmony_ci # 编译hats测试用例 40012e714ceSopenharmony_ci ./build.sh suite=hats system_size=standard product_name=rk3568 40112e714ceSopenharmony_ci 40212e714ceSopenharmony_ci # 回到代码根目录 40312e714ceSopenharmony_ci cd - 40412e714ceSopenharmony_ci ``` 40512e714ceSopenharmony_ci 编译好的测试用例可执行文件```HatsHdfNnrtFunctionTest```会输出到```out/rk3568/suites/hats/testcases/```下。 40612e714ceSopenharmony_ci 40712e714ceSopenharmony_ci2. 将测试用例push到RK3568设备的```/data/local/tmp/```目录下。 40812e714ceSopenharmony_ci ```shell 40912e714ceSopenharmony_ci # 将测试用例可执行文件推送到设备上,HatsHdfNnrtFunctionTest是测试用例可执行文件。 41012e714ceSopenharmony_ci hdc_std file send out/rk3568/suites/hats/testcases/HartsHdfNnrtFunctionTest /data/local/tmp/ 41112e714ceSopenharmony_ci 41212e714ceSopenharmony_ci # 给测试用例可执行文件加上权限。 41312e714ceSopenharmony_ci hdc_std shell "chmod +x /data/local/tmp/HatsHdfNnrtFunctionTest" 41412e714ceSopenharmony_ci ``` 41512e714ceSopenharmony_ci 41612e714ceSopenharmony_ci3. 执行用例并查看结果。 41712e714ceSopenharmony_ci ```shell 41812e714ceSopenharmony_ci # 执行测试用例 41912e714ceSopenharmony_ci hdc_std shell "/data/local/tmp/HatsHdfNnrtFunctionTest" 42012e714ceSopenharmony_ci ``` 42112e714ceSopenharmony_ci 42212e714ceSopenharmony_ci 测试报告显示已通过47个用例,说明所有hats用例已执行成功,服务已通过兼容性测试。 42312e714ceSopenharmony_ci ```text 42412e714ceSopenharmony_ci ... 42512e714ceSopenharmony_ci [----------] Global test environment tear-down 42612e714ceSopenharmony_ci Gtest xml output finished 42712e714ceSopenharmony_ci [==========] 47 tests from 3 test suites ran. (515 ms total) 42812e714ceSopenharmony_ci [ PASSED ] 47 tests. 42912e714ceSopenharmony_ci ``` 43012e714ceSopenharmony_ci 43112e714ceSopenharmony_ci### 开发实例 43212e714ceSopenharmony_ci完整Demo代码可以参考[社区实现](https://gitee.com/openharmony/ai_neural_network_runtime/tree/master/example/drivers)。 43312e714ceSopenharmony_ci 43412e714ceSopenharmony_ci1. 进入OpenHarmony源码根目录,在```drivers/peripheral```路径下创建```nnrt```目录,拷贝NNRt源码路径```foundation/ai/neural_network_runtime```下的```example/driver/nnrt/v2_0```目录到```drivers/peripheral/nnrt```路径下。 43512e714ceSopenharmony_ci ```shell 43612e714ceSopenharmony_ci cp -r example/drivers/nnrt/v2_0 drivers/peripheral/nnrt 43712e714ceSopenharmony_ci ``` 43812e714ceSopenharmony_ci 43912e714ceSopenharmony_ci2. 在```drivers/peripheral/nnrt```下补充```bundle.json```文件,```bundle.json```的写法参考本教程上面[开发步骤](#开发步骤)中的[实现HDI服务](#实现hdi服务)章节。 44012e714ceSopenharmony_ci 44112e714ceSopenharmony_ci3. 由于Demo依赖MindSpore Lite CPU算子,因此需要添加MindSpore Lite依赖文件: 44212e714ceSopenharmony_ci - 在```drivers/peripheral/nnrt/v2_0```下创建```mindspore```目录,用于存放mindspore动态库和头文件。 44312e714ceSopenharmony_ci ```shell 44412e714ceSopenharmony_ci mkdir drivers/peripheral/nnrt/v2_0/mindspore 44512e714ceSopenharmony_ci ``` 44612e714ceSopenharmony_ci - 将所需的头文件拷贝到```drivers/peripheral/nnrt/v2_0/mindspore```目录下。 44712e714ceSopenharmony_ci ```shell 44812e714ceSopenharmony_ci cp -r third_party/mindspore/mindspore-src/source/include drivers/peripheral/nnrt/v2_0/mindspore 44912e714ceSopenharmony_ci cp -r third_party/mindspore/mindspore-src/source/mindspore/core/mindapi drivers/peripheral/nnrt/v2_0/mindspore/include/ 45012e714ceSopenharmony_ci ``` 45112e714ceSopenharmony_ci - Demo还依赖mindspore的```schema```文件: 45212e714ceSopenharmony_ci ```shell 45312e714ceSopenharmony_ci # 创建mindspore_schema目录 45412e714ceSopenharmony_ci mkdir drivers/peripheral/nnrt/v2_0/hdi_cpu_service/include/mindspore_schema 45512e714ceSopenharmony_ci 45612e714ceSopenharmony_ci # 从third_party目录拷贝mindspore schema文件 45712e714ceSopenharmony_ci cp third_party/mindspore/mindspore/lite/schema/* drivers/peripheral/nnrt/v2_0/hdi_cpu_service/include/mindspore_schema/ 45812e714ceSopenharmony_ci ``` 45912e714ceSopenharmony_ci - 编译OpenHarmony的MindSpore Lite动态库,并将动态库拷贝到```mindspore```目录下。 46012e714ceSopenharmony_ci ```shell 46112e714ceSopenharmony_ci # 编译mindspore动态库 46212e714ceSopenharmony_ci ./build.sh --product-name rk3568 -ccaache --jobs 4 --build-target mindspore_lib 46312e714ceSopenharmony_ci 46412e714ceSopenharmony_ci # 在drivers/peripheral/nnrt/v2_0/mindspore下创建mindspore目录 46512e714ceSopenharmony_ci mkdir drivers/peripheral/nnrt/v2_0/mindspore/mindspore 46612e714ceSopenharmony_ci 46712e714ceSopenharmony_ci # 从out目录将mindspore动态库拷贝到drivers/peripheral/nnrt/v2_0/mindspore/mindspore下 46812e714ceSopenharmony_ci cp out/rk3568/package/phone/system/lib/libmindspore-lite.so drivers/peripheral/nnrt/v2_0/mindspore/mindspore/ 46912e714ceSopenharmony_ci ``` 47012e714ceSopenharmony_ci4. 其他配置请参考本教程上面的[开发步骤](#开发步骤)章节。