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