Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * @file uint_tensor.h
4 : * @date 02 April 2024
5 : * @brief This is UIntTensor class for unsigned integer calculation
6 : * @see https://github.com/nnstreamer/nntrainer
7 : * @author Donghyeon Jeong <dhyeon.jeong@samsung.com>
8 : * @author Eunju Yang <ej.yang@samsung.com>
9 : * @bug No known bugs except for NYI items
10 : */
11 :
12 : #ifndef __UINT_TENSOR_H__
13 : #define __UINT_TENSOR_H__
14 : #ifdef __cplusplus
15 :
16 : #include <cpu_backend.h>
17 : #include <iomanip>
18 : #include <iostream>
19 : #include <tensor.h>
20 : #include <tensor_base.h>
21 :
22 : namespace nntrainer {
23 :
24 : /**
25 : * @class UIntTensor class : Template <typename T>
26 : * @brief UIntTensor class for T-bit unsigned integer calculation
27 : * For typename, uint8_t, uint16_t, uint32_t are supported.
28 : */
29 : template <typename T> class UIntTensor : public TensorBase {
30 : public:
31 : /**
32 : * @brief Basic Constructor of Tensor
33 : */
34 : UIntTensor(std::string name_ = "", Tformat fm = Tformat::NCHW,
35 : QScheme qscheme_ = QScheme::PER_TENSOR_AFFINE);
36 :
37 : /**
38 : * @brief Construct a new UIntTensor object
39 : *
40 : * @param d Tensor dim for this float tensor
41 : * @param alloc_now Allocate memory to this tensor or not
42 : * @param init Initializer for the tensor
43 : * @param name Name of the tensor
44 : * @param qscheme_ quantization scheme
45 : */
46 : UIntTensor(const TensorDim &d, bool alloc_now,
47 : Initializer init = Initializer::NONE, std::string name = "",
48 : QScheme qscheme_ = QScheme::PER_TENSOR_AFFINE);
49 :
50 : /**
51 : * @brief Construct a new UIntTensor object
52 : *
53 : * @param d Tensor dim for this tensor
54 : * @param buf buffer
55 : * @param qscheme_ quantization scheme
56 : */
57 : UIntTensor(const TensorDim &d, const void *buf = nullptr,
58 : QScheme qscheme_ = QScheme::PER_TENSOR_AFFINE);
59 :
60 : /**
61 : * @brief Construct a new UIntTensor object
62 : *
63 : * @param d data for the Tensor
64 : * @param scales scale factors for the Tensor
65 : * @param zero_points zero_points for the Tensor
66 : * @param fm format for the Tensor
67 : * @param qscheme_ quantization scheme
68 : */
69 : UIntTensor(std::vector<std::vector<std::vector<std::vector<T>>>> const &d,
70 : std::vector<float> const &scales,
71 : std::vector<unsigned int> const &zero_points, Tformat fm,
72 : QScheme qscheme_);
73 :
74 : /**
75 : * @brief Construct a new UIntTensor object
76 : * @param rhs TensorBase object to copy
77 : */
78 11 : UIntTensor(TensorBase &rhs) :
79 11 : TensorBase(rhs), qscheme(QScheme::PER_TENSOR_AFFINE) {}
80 :
81 : /**
82 : * @brief Basic Destructor
83 : */
84 70 : ~UIntTensor() {}
85 :
86 : /**
87 : * @brief Comparison operator overload
88 : * @param[in] rhs Tensor to be compared with
89 : */
90 : bool operator==(const UIntTensor &rhs) const;
91 :
92 : /**
93 : * @brief Comparison operator overload
94 : * @param[in] rhs Tensor to be compared with
95 : */
96 0 : bool operator!=(const UIntTensor &rhs) const { return !(*this == rhs); }
97 :
98 : /**
99 : * @copydoc Tensor::allocate()
100 : */
101 : void allocate() override;
102 :
103 : /**
104 : * @copydoc Tensor::deallocate()
105 : */
106 : void deallocate() override;
107 :
108 : /**
109 : * @copydoc Tensor::getData()
110 : */
111 : void *getData() const override;
112 :
113 : /**
114 : * @copydoc Tensor::getData(size_t idx)
115 : */
116 : void *getData(size_t idx) const override;
117 :
118 : /**
119 : * @copydoc Tensor::getScale()
120 : */
121 : void *getScale() const override;
122 :
123 : /**
124 : * @copydoc Tensor::getScale(size_t idx)
125 : */
126 : void *getScale(size_t idx) const override;
127 :
128 : /**
129 : * @copydoc Tensor::getZeroPoint()
130 : */
131 : unsigned int *getZeroPoint() const override;
132 :
133 : /**
134 : * @copydoc Tensor::getZeroPoint(size_t idx)
135 : */
136 : unsigned int *getZeroPoint(size_t idx) const override;
137 :
138 : /**
139 : * @brief i data index
140 : * @retval address of ith data
141 : */
142 : void *getAddress(unsigned int i) override;
143 :
144 : /**
145 : * @brief i data index
146 : * @retval address of ith data
147 : */
148 : const void *getAddress(unsigned int i) const override;
149 :
150 : /**
151 : * @brief return value at specific location
152 : * @param[in] i index
153 : */
154 : const T &getValue(unsigned int i) const;
155 :
156 : /**
157 : * @brief return value at specific location
158 : * @param[in] i index
159 : */
160 : T &getValue(unsigned int i);
161 :
162 : /**
163 : * @brief return value at specific location
164 : * @param[in] b batch location
165 : * @param[in] c channel location
166 : * @param[in] h height location
167 : * @param[in] w width location
168 : */
169 : const T &getValue(unsigned int b, unsigned int c, unsigned int h,
170 : unsigned int w) const;
171 :
172 : /**
173 : * @brief return value at specific location
174 : * @param[in] b batch location
175 : * @param[in] c channel location
176 : * @param[in] h height location
177 : * @param[in] w width location
178 : */
179 : T &getValue(unsigned int b, unsigned int c, unsigned int h, unsigned int w);
180 :
181 : /**
182 : * @copydoc Tensor::setValue(float value)
183 : */
184 : void setValue(float value) override;
185 :
186 : /**
187 : * @copydoc Tensor::setValue(b, c, h, w, value)
188 : */
189 : void setValue(unsigned int b, unsigned int c, unsigned int h, unsigned int w,
190 : float value) override;
191 :
192 : /**
193 : * @copydoc Tensor::addValue(b, c, h, w, value, beta)
194 : */
195 : void addValue(unsigned int b, unsigned int c, unsigned int h, unsigned int w,
196 : float value, float beta) override;
197 :
198 : /**
199 : * @copydoc Tensor::setZero()
200 : */
201 : void setZero() override;
202 :
203 : /**
204 : * @copydoc Tensor::initialize()
205 : */
206 : void initialize() override;
207 :
208 : /**
209 : * @copydoc Tensor::initialize(Initializer init)
210 : */
211 : void initialize(Initializer init) override;
212 :
213 : /**
214 : * @copydoc Tensor::copy(const Tensor &from)
215 : */
216 : void copy(const Tensor &from) override;
217 :
218 : /**
219 : * @copydoc Tensor::copyData(const Tensor &from)
220 : */
221 : void copyData(const Tensor &from) override;
222 :
223 : /**
224 : * @copydoc Tensor::copy_with_stride()
225 : */
226 : void copy_with_stride(const Tensor &input, Tensor &output) override;
227 :
228 : /**
229 : * @copydoc Tensor::save(std::ostream &file)
230 : */
231 : void save(std::ostream &file) override;
232 :
233 : /**
234 : * @copydoc Tensor::read(std::ifstream &file)
235 : */
236 : void read(std::ifstream &file, size_t start_offset,
237 : bool read_from_offset) override;
238 :
239 : /**
240 : * @copydoc Tensor::read(ReadSource src)
241 : */
242 : void read(ReadSource src, size_t start_offset,
243 : bool read_from_offset) override;
244 :
245 : /**
246 : * @copydoc Tensor::argmax()
247 : */
248 : std::vector<unsigned int> argmax() const override;
249 :
250 : /**
251 : * @copydoc Tensor::argmin()
252 : */
253 : std::vector<unsigned int> argmin() const override;
254 :
255 : /**
256 : * @copydoc Tensor::max_abs()
257 : */
258 : float max_abs() const override;
259 :
260 : /**
261 : * @copydoc Tensor::maxValue()
262 : */
263 : float maxValue() const override;
264 :
265 : /**
266 : * @copydoc Tensor::minValue()
267 : */
268 : float minValue() const override;
269 :
270 : /**
271 : * @copydoc Tensor::print(std::ostream &out)
272 : */
273 : void print(std::ostream &out) const override;
274 :
275 : /**
276 : * @copydoc Tensor::getMemoryBytes()
277 : */
278 : size_t getMemoryBytes() const override;
279 :
280 : /**
281 : * @copydoc TensorBase::save_quantization_info()
282 : */
283 : void save_quantization_info(std::ostream &file) override;
284 :
285 : /**
286 : * @copydoc TensorBase::read_quantization_info()
287 : */
288 : void read_quantization_info(std::ifstream &file, size_t start_offset,
289 : bool read_from_offset) override;
290 :
291 : /**
292 : * @copydoc TensorBase::read_quantization_info()
293 : */
294 : void read_quantization_info(ReadSource src, size_t start_offset,
295 : bool read_from_offset) override;
296 :
297 : /**
298 : * @copydoc Tensor::scale_size()
299 : */
300 : size_t scale_size() const override;
301 :
302 : /**
303 : * @copydoc Tensor::q_scheme()
304 : */
305 : QScheme q_scheme() const override;
306 :
307 : private:
308 : /**
309 : * @brief quantization scheme
310 : */
311 : QScheme qscheme = QScheme::PER_TENSOR_AFFINE;
312 :
313 : /**
314 : * @brief copy a buffer to @a this, the caller has to ensure that @a this is
315 : * initialized otherwise undefined behavior
316 : *
317 : * @param buf buffer to copy from
318 : */
319 : void copy(const void *buf);
320 :
321 : /**
322 : * @brief Get the Data Type String object
323 : * @return std::string of tensor data type (UINT16)
324 : */
325 4 : std::string getStringDataType() const override {
326 4 : if (typeid(T) == typeid(uint8_t))
327 1 : return "UINT8";
328 3 : else if (typeid(T) == typeid(uint16_t))
329 2 : return "UINT16";
330 1 : else if (typeid(T) == typeid(uint32_t))
331 1 : return "UINT32";
332 : else
333 0 : throw std::runtime_error("unsupported type");
334 : }
335 :
336 : /**
337 : * @brief check Tensor Data Type (to briefly support template)
338 : * @return Tdatatype
339 : */
340 8 : Tdatatype checkTensorDataType() const {
341 8 : if (typeid(T) == typeid(uint8_t))
342 : return Tdatatype::UINT8;
343 6 : else if (typeid(T) == typeid(uint16_t))
344 : return Tdatatype::UINT16;
345 2 : else if (typeid(T) == typeid(uint32_t))
346 : return Tdatatype::UINT32;
347 : else
348 0 : throw std::runtime_error("unsupported type");
349 : }
350 :
351 : /**
352 : * @copydoc Tensor::isValid()
353 : */
354 0 : bool isValid() const override { return true; }; // NYI
355 : };
356 :
357 : /****** Alias for UIntTensors ******/
358 : using UInt8Tensor = UIntTensor<uint8_t>;
359 : using UInt16Tensor = UIntTensor<uint16_t>;
360 : using UInt32Tensor = UIntTensor<uint32_t>;
361 :
362 : /**** Declare Template classes *****/
363 : template class UIntTensor<uint8_t>;
364 : template class UIntTensor<uint16_t>;
365 : template class UIntTensor<uint32_t>;
366 :
367 : /**
368 : * Define UIntTenosr's template class methods.
369 : * Template methods should be defined with declaration.
370 : * To this end, include implementation file
371 : */
372 : #include <uint_tensor.cpp>
373 :
374 : } // namespace nntrainer
375 :
376 : #endif /* __cplusplus */
377 : #endif /* __UINT_TENSOR_H__ */
|