1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdi_prepared_model_v1_0.h"
17
18 #include "common/log.h"
19 #include "memory_manager.h"
20
21 namespace OHOS {
22 namespace NeuralNetworkRuntime {
23 namespace {
TransDataType(const OH_NN_DataType & dataType)24 V1_0::DataType TransDataType(const OH_NN_DataType& dataType)
25 {
26 switch (dataType) {
27 case OH_NN_BOOL:
28 return V1_0::DataType::DATA_TYPE_BOOL;
29 case OH_NN_INT8:
30 return V1_0::DataType::DATA_TYPE_INT8;
31 case OH_NN_INT16:
32 return V1_0::DataType::DATA_TYPE_INT16;
33 case OH_NN_INT32:
34 return V1_0::DataType::DATA_TYPE_INT32;
35 case OH_NN_INT64:
36 return V1_0::DataType::DATA_TYPE_INT64;
37 case OH_NN_UINT8:
38 return V1_0::DataType::DATA_TYPE_UINT8;
39 case OH_NN_UINT16:
40 return V1_0::DataType::DATA_TYPE_UINT16;
41 case OH_NN_UINT32:
42 return V1_0::DataType::DATA_TYPE_UINT32;
43 case OH_NN_UINT64:
44 return V1_0::DataType::DATA_TYPE_UINT64;
45 case OH_NN_FLOAT16:
46 return V1_0::DataType::DATA_TYPE_FLOAT16;
47 case OH_NN_FLOAT32:
48 return V1_0::DataType::DATA_TYPE_FLOAT32;
49 case OH_NN_FLOAT64:
50 return V1_0::DataType::DATA_TYPE_FLOAT64;
51 default:
52 return V1_0::DataType::DATA_TYPE_UNKNOWN;
53 }
54 }
55
TransFormat(const OH_NN_Format & format)56 V1_0::Format TransFormat(const OH_NN_Format& format)
57 {
58 switch (format) {
59 case OH_NN_FORMAT_NCHW:
60 return V1_0::Format::FORMAT_NCHW;
61 case OH_NN_FORMAT_NHWC:
62 return V1_0::Format::FORMAT_NHWC;
63 default:
64 return V1_0::Format::FORMAT_NONE;
65 }
66 }
67
TransIOTensor(const IOTensor & tensor)68 V1_0::IOTensor TransIOTensor(const IOTensor& tensor)
69 {
70 V1_0::IOTensor iTensor;
71 iTensor.name = tensor.name;
72 iTensor.dataType = TransDataType(tensor.dataType);
73 iTensor.dimensions = tensor.dimensions;
74 iTensor.format = TransFormat(tensor.format);
75
76 V1_0::SharedBuffer iBuffer {INVALID_FD, 0, 0, 0};
77 if (tensor.data != nullptr) {
78 auto memManager = MemoryManager::GetInstance();
79 Memory memory;
80 auto ret = memManager->GetMemory(tensor.data, memory);
81 if (ret != OH_NN_SUCCESS) {
82 LOGE("Invalid Tensor buffer, cannot transform to fd.");
83 } else {
84 iBuffer.fd = memory.fd;
85 iBuffer.bufferSize = memory.length;
86 iBuffer.offset = 0;
87 iBuffer.dataSize = memory.length;
88 }
89 }
90 iTensor.data = iBuffer;
91
92 return iTensor;
93 }
94 } // unamed namespace
95
HDIPreparedModelV1_0(OHOS::sptr<V1_0::IPreparedModel> hdiPreparedModel)96 HDIPreparedModelV1_0::HDIPreparedModelV1_0(OHOS::sptr<V1_0::IPreparedModel> hdiPreparedModel)
97 : m_hdiPreparedModel(hdiPreparedModel)
98 {
99 hdiPreparedModel->GetVersion(m_hdiVersion.first, m_hdiVersion.second);
100 }
101
ExportModelCache(std::vector<Buffer> & modelCache)102 OH_NN_ReturnCode HDIPreparedModelV1_0::ExportModelCache(std::vector<Buffer>& modelCache)
103 {
104 if (!modelCache.empty()) {
105 LOGE("The vector of modelCache should be empty. size=%zu", modelCache.size());
106 return OH_NN_INVALID_PARAMETER;
107 }
108
109 std::vector<V1_0::SharedBuffer> iBuffers;
110 auto ret = m_hdiPreparedModel->ExportModelCache(iBuffers);
111 if (ret != HDF_SUCCESS) {
112 LOGE("Export model cache failed. ErrorCode=%d", ret);
113 return OH_NN_UNAVALIDABLE_DEVICE;
114 }
115
116 auto memManager = MemoryManager::GetInstance();
117 size_t iBuffersSize = iBuffers.size();
118 for (size_t i = 0; i < iBuffersSize; i++) {
119 auto addr = memManager->MapMemory(iBuffers[i].fd, iBuffers[i].bufferSize);
120 if (addr == nullptr) {
121 LOGE("Export the %zuth model cache failed, cannot not map fd to address.", i + 1);
122 return OH_NN_MEMORY_ERROR;
123 }
124 Buffer modelbuffer {addr, iBuffers[i].bufferSize};
125 modelCache.emplace_back(modelbuffer);
126 }
127
128 return OH_NN_SUCCESS;
129 }
130
Run(const std::vector<IOTensor> & inputs,const std::vector<IOTensor> & outputs,std::vector<std::vector<int32_t>> & outputsDims,std::vector<bool> & isOutputBufferEnough)131 OH_NN_ReturnCode HDIPreparedModelV1_0::Run(const std::vector<IOTensor>& inputs, const std::vector<IOTensor>& outputs,
132 std::vector<std::vector<int32_t>>& outputsDims, std::vector<bool>& isOutputBufferEnough)
133 {
134 V1_0::IOTensor iTensor;
135 std::vector<V1_0::IOTensor> iInputTensors;
136 for (auto& input: inputs) {
137 iTensor = TransIOTensor(input);
138 if (iTensor.data.fd == INVALID_FD) {
139 LOGE("Transform inputs tensor failed, cannot find data file descriptor.");
140 return OH_NN_INVALID_PARAMETER;
141 }
142 iInputTensors.emplace_back(iTensor);
143 }
144
145 std::vector<V1_0::IOTensor> iOutputTensors;
146 for (auto& output: outputs) {
147 iTensor = TransIOTensor(output);
148 if (iTensor.data.fd == INVALID_FD) {
149 LOGE("Transform outputs tensor failed, cannot find data file descriptor.");
150 return OH_NN_INVALID_PARAMETER;
151 }
152 iOutputTensors.emplace_back(iTensor);
153 }
154
155 auto ret = m_hdiPreparedModel->Run(iInputTensors, iOutputTensors, outputsDims, isOutputBufferEnough);
156 if (ret != HDF_SUCCESS || outputsDims.empty()) {
157 LOGE("Run model failed. ErrorCode=%d", ret);
158 return OH_NN_UNAVALIDABLE_DEVICE;
159 }
160
161 return OH_NN_SUCCESS;
162 }
163 } // namespace NeuralNetworkRuntime
164 } // OHOS