xref: /aosp_15_r20/external/executorch/backends/qualcomm/aot/wrappers/TensorWrapper.cpp (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1 /*
2  * Copyright (c) Qualcomm Innovation Center, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <executorch/backends/qualcomm/aot/wrappers/TensorWrapper.h>
10 
11 #include <atomic>
12 #include <cstring>
13 #include <limits>
14 #include <numeric>
15 namespace executorch {
16 namespace backends {
17 namespace qnn {
18 
19 using executorch::runtime::Error;
20 
GetDataTypeSize(Qnn_DataType_t data_type)21 std::uint32_t GetDataTypeSize(Qnn_DataType_t data_type) {
22   std::uint32_t size = 0;
23 
24   switch (data_type) {
25     case QNN_DATATYPE_INT_8:
26     case QNN_DATATYPE_UINT_8:
27     case QNN_DATATYPE_SFIXED_POINT_8:
28     case QNN_DATATYPE_UFIXED_POINT_8:
29     case QNN_DATATYPE_BOOL_8:
30       size = sizeof(std::uint8_t);
31       break;
32     case QNN_DATATYPE_INT_16:
33     case QNN_DATATYPE_UINT_16:
34     case QNN_DATATYPE_FLOAT_16:
35     case QNN_DATATYPE_SFIXED_POINT_16:
36     case QNN_DATATYPE_UFIXED_POINT_16:
37       size = sizeof(std::uint16_t);
38       break;
39     case QNN_DATATYPE_INT_32:
40     case QNN_DATATYPE_UINT_32:
41     case QNN_DATATYPE_FLOAT_32:
42     case QNN_DATATYPE_SFIXED_POINT_32:
43     case QNN_DATATYPE_UFIXED_POINT_32:
44       size = sizeof(float);
45       break;
46     case QNN_DATATYPE_INT_64:
47     case QNN_DATATYPE_UINT_64:
48       size = sizeof(std::uint64_t);
49       break;
50     case QNN_DATATYPE_UNDEFINED:
51     default:
52       size = 0;
53   }
54 
55   return size;
56 }
57 
58 std::atomic<std::uint32_t> intermediate_tensor_id{
59     std::numeric_limits<std::uint32_t>::max()};
60 
CreateIntermediateTensorId()61 std::uint32_t CreateIntermediateTensorId() {
62   return --intermediate_tensor_id;
63 }
64 
TensorWrapper(const std::string & tensor_name,Qnn_TensorType_t tensor_type,Qnn_DataType_t data_type,std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,std::uint32_t rank,const std::uint32_t dims[],std::uint32_t bytes,const void * data,bool copy_data)65 TensorWrapper::TensorWrapper(
66     const std::string& tensor_name,
67     Qnn_TensorType_t tensor_type,
68     Qnn_DataType_t data_type,
69     std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,
70     std::uint32_t rank,
71     const std::uint32_t dims[],
72     std::uint32_t bytes,
73     const void* data,
74     bool copy_data)
75     : qnn_tensor_name_(tensor_name),
76       quantize_param_wrapper_(std::move(quantize_param_wrapper)),
77       dims_(dims, dims + rank),
78       bytes_(bytes),
79       owned_data_(nullptr) {
80   // "version" is the only exception that we don't need QNN_VER_PTR wrapper.
81   tensor_.version = QNN_TENSOR_VERSION_1;
82 
83   // Don't assign .id because it's an output field.
84   QNN_VER_PTR(tensor_)->name = qnn_tensor_name_.c_str();
85   QNN_VER_PTR(tensor_)->dimensions = dims_.data();
86   QNN_VER_PTR(tensor_)->type = tensor_type;
87   QNN_VER_PTR(tensor_)->dataFormat = QNN_TENSOR_DATA_FORMAT_FLAT_BUFFER;
88   QNN_VER_PTR(tensor_)->dataType = data_type;
89   QNN_VER_PTR(tensor_)->quantizeParams =
90       quantize_param_wrapper_->CreateQuantizeParams();
91   QNN_VER_PTR(tensor_)->rank = rank;
92   QNN_VER_PTR(tensor_)->memType = QNN_TENSORMEMTYPE_RAW;
93 
94   if (data != nullptr) {
95     QNN_VER_PTR(tensor_)->clientBuf.dataSize = bytes;
96 
97     if (tensor_type != QNN_TENSOR_TYPE_STATIC) {
98       QNN_VER_PTR(tensor_)->clientBuf.data = nullptr;
99     } else if (copy_data) {
100       owned_data_ = std::make_unique<char[]>(bytes);
101       const char* src_data = static_cast<const char*>(data);
102       std::memcpy(owned_data_.get(), src_data, bytes);
103       QNN_VER_PTR(tensor_)->clientBuf.data = owned_data_.get();
104     } else {
105       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
106       QNN_VER_PTR(tensor_)->clientBuf.data = const_cast<void*>(data);
107     }
108   }
109 }
110 
FillDataBuffer(const void * data,bool copy_data)111 Error TensorWrapper::FillDataBuffer(const void* data, bool copy_data) {
112   if (data != nullptr) {
113     QNN_VER_PTR(tensor_)->memType = QNN_TENSORMEMTYPE_RAW;
114     QNN_VER_PTR(tensor_)->clientBuf.dataSize = bytes_;
115     if (copy_data) {
116       owned_data_ = std::make_unique<char[]>(bytes_);
117       const char* src_data = static_cast<const char*>(data);
118       std::memcpy(owned_data_.get(), src_data, bytes_);
119       QNN_VER_PTR(tensor_)->clientBuf.data = owned_data_.get();
120     } else {
121       // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
122       QNN_VER_PTR(tensor_)->clientBuf.data = const_cast<void*>(data);
123     }
124   } else {
125     QNN_EXECUTORCH_LOG_WARN("Data pointer is nullptr");
126   }
127   return Error::Ok;
128 }
129 
AllocateDataBuffer()130 Error TensorWrapper::AllocateDataBuffer() {
131   char* static_data_buffer = new (std::nothrow) char[bytes_]; // NOLINT
132   if (static_data_buffer == nullptr) {
133     return Error::Internal;
134   }
135   owned_data_ = std::unique_ptr<char[]>(static_data_buffer);
136   QNN_VER_PTR(tensor_)->memType = QNN_TENSORMEMTYPE_RAW;
137   QNN_VER_PTR(tensor_)->clientBuf.dataSize = bytes_;
138   QNN_VER_PTR(tensor_)->clientBuf.data = owned_data_.get();
139 
140   return Error::Ok;
141 }
142 
UpdateQnnTensorMeta(const Qnn_Tensor_t & tensor_src)143 void TensorWrapper::UpdateQnnTensorMeta(const Qnn_Tensor_t& tensor_src) {
144   QNN_VER_PTR(tensor_)->id = QNN_VER_PTR(tensor_src)->id;
145 }
146 
SetName(const std::string & name)147 Error TensorWrapper::SetName(const std::string& name) {
148   qnn_tensor_name_ = name;
149   QNN_VER_PTR(tensor_)->name = qnn_tensor_name_.c_str();
150   return Error::Ok;
151 }
152 
SetMemHandle(Qnn_MemHandle_t mem_handle)153 Error TensorWrapper::SetMemHandle(Qnn_MemHandle_t mem_handle) {
154   QNN_VER_PTR(tensor_)->memType = QNN_TENSORMEMTYPE_MEMHANDLE;
155   QNN_VER_PTR(tensor_)->memHandle = mem_handle;
156   return Error::Ok;
157 }
158 
159 // base function for Create TensorWrapper
CreateTensorWrapper(const std::string & tensor_name,Qnn_TensorType_t tensor_type,Qnn_DataType_t data_type,std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,std::uint32_t rank,const std::uint32_t dims[],std::uint32_t bytes,const void * data,bool copy_data)160 std::shared_ptr<TensorWrapper> CreateTensorWrapper(
161     const std::string& tensor_name,
162     Qnn_TensorType_t tensor_type,
163     Qnn_DataType_t data_type,
164     std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,
165     std::uint32_t rank,
166     const std::uint32_t dims[],
167     std::uint32_t bytes,
168     const void* data,
169     bool copy_data) {
170   if (bytes == 0) {
171     bytes = std::accumulate(
172         dims, dims + rank, GetDataTypeSize(data_type), std::multiplies<>());
173   }
174   return std::make_shared<TensorWrapper>(
175       tensor_name,
176       tensor_type,
177       data_type,
178       std::move(quantize_param_wrapper),
179       rank,
180       dims,
181       bytes,
182       data,
183       copy_data);
184 }
185 
CreateTensorWrapper(Qnn_TensorType_t tensor_type,Qnn_DataType_t data_type,std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,std::uint32_t rank,const std::uint32_t dims[],std::uint32_t bytes,const void * data,bool copy_data)186 std::shared_ptr<TensorWrapper> CreateTensorWrapper(
187     Qnn_TensorType_t tensor_type,
188     Qnn_DataType_t data_type,
189     std::unique_ptr<QuantizeParamsWrapper> quantize_param_wrapper,
190     std::uint32_t rank,
191     const std::uint32_t dims[],
192     std::uint32_t bytes,
193     const void* data,
194     bool copy_data) {
195   return CreateTensorWrapper(
196       std::to_string(CreateIntermediateTensorId()),
197       tensor_type,
198       data_type,
199       std::move(quantize_param_wrapper),
200       rank,
201       dims,
202       bytes,
203       data,
204       copy_data);
205 }
206 
207 // Factory functions to create TensorWrappers
CreateTensorWrapper(const Qnn_Tensor_t & tensor)208 std::shared_ptr<TensorWrapper> CreateTensorWrapper(const Qnn_Tensor_t& tensor) {
209   return CreateTensorWrapper(
210       std::string(QNN_VER_PTR(tensor)->name),
211       QNN_VER_PTR(tensor)->type,
212       QNN_VER_PTR(tensor)->dataType,
213       CreateQuantizationParamWrapper(QNN_VER_PTR(tensor)->quantizeParams),
214       QNN_VER_PTR(tensor)->rank,
215       QNN_VER_PTR(tensor)->dimensions,
216       QNN_VER_PTR(tensor)->clientBuf.dataSize,
217       QNN_VER_PTR(tensor)->clientBuf.data);
218 }
219 } // namespace qnn
220 } // namespace backends
221 } // namespace executorch
222