Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * @file float_tensor.h
4 : * @date 01 December 2023
5 : * @brief This is FloatTensor class for 32-bit floating point calculation
6 : * @see https://github.com/nntrainer/nntrainer
7 : * @author Jijoong Moon <jijoong.moon@samsung.com>
8 : * @author Donghyeon Jeong <dhyeon.jeong@samsung.com>
9 : * @bug No known bugs except for NYI items
10 : */
11 :
12 : #ifndef __FLOAT_TENSOR_H__
13 : #define __FLOAT_TENSOR_H__
14 : #ifdef __cplusplus
15 :
16 : #include <tensor_base.h>
17 :
18 : #ifdef DEBUG
19 : #define EXCEPT_WHEN_DEBUG
20 : #else
21 : #define EXCEPT_WHEN_DEBUG noexcept
22 : #endif
23 :
24 : namespace nntrainer {
25 :
26 : /**
27 : * @class FloatTensor class
28 : * @brief FloatTensor class for 32-bit floating point calculation
29 : */
30 : class FloatTensor : public TensorBase {
31 : public:
32 : /**
33 : * @brief Basic Constructor of Tensor
34 : */
35 : FloatTensor(std::string name_ = "", Tformat fm = Tformat::NCHW);
36 :
37 : /**
38 : * @brief Construct a new FloatTensor 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 : */
45 : FloatTensor(const TensorDim &d, bool alloc_now,
46 : Initializer init = Initializer::NONE, std::string name = "");
47 :
48 : /**
49 : * @brief Construct a new FloatTensor object
50 : *
51 : * @param d Tensor dim for this tensor
52 : * @param buf buffer
53 : */
54 : FloatTensor(const TensorDim &d, const void *buf = nullptr);
55 :
56 : /**
57 : * @brief Construct a new FloatTensor object
58 : *
59 : * @param d data for the Tensor
60 : * @param fm format for the Tensor
61 : */
62 31 : FloatTensor(
63 : std::vector<std::vector<std::vector<std::vector<float>>>> const &d,
64 62 : Tformat fm) {
65 31 : if (d.empty() || d[0].empty() || d[0][0].empty() || d[0][0][0].empty()) {
66 : throw std::out_of_range(
67 1 : "[Tensor] trying to initialize FloatTensor from empty vector");
68 : }
69 :
70 30 : dim.setTensorDim(0, d.size());
71 30 : if (fm == Tformat::NCHW) {
72 28 : dim.setTensorDim(1, d[0].size());
73 28 : dim.setTensorDim(2, d[0][0].size());
74 28 : dim.setTensorDim(3, d[0][0][0].size());
75 : } else {
76 2 : dim.setTensorDim(2, d[0].size());
77 2 : dim.setTensorDim(3, d[0][0].size());
78 2 : dim.setTensorDim(1, d[0][0][0].size());
79 : }
80 :
81 : dim.setTensorType({fm, Tdatatype::FP32});
82 :
83 30 : strides = dim.computeStrides();
84 30 : contiguous = true;
85 30 : initializer = Initializer::NONE;
86 :
87 : MemoryData *mem_data =
88 833 : new MemoryData((void *)(new float[dim.getDataLen()]()));
89 31 : data = std::shared_ptr<MemoryData>(mem_data, [](MemoryData *ptr) {
90 30 : delete[] ptr->getAddr<float>();
91 30 : delete ptr;
92 : });
93 :
94 30 : offset = 0;
95 :
96 : // if fm == Tformat::NCHW, then dim[0] == batch , dim[1] == channel, dim[2]
97 : // == height, dim[3] == width. and if fm == Tformat::NHWC, dim[0] == batch,
98 : // dim[1] == height, dim[2] == width, dim[3] == channel
99 30 : if (fm == Tformat::NCHW) {
100 91 : for (unsigned int i = 0; i < batch(); ++i)
101 163 : for (unsigned int j = 0; j < channel(); ++j)
102 226 : for (unsigned int k = 0; k < height(); ++k)
103 923 : for (unsigned int l = 0; l < width(); ++l)
104 797 : this->setValue(i, j, k, l, d[i][j][k][l]);
105 : } else {
106 4 : for (unsigned int i = 0; i < batch(); ++i)
107 4 : for (unsigned int j = 0; j < height(); ++j)
108 8 : for (unsigned int k = 0; k < width(); ++k)
109 12 : for (unsigned int l = 0; l < channel(); ++l)
110 6 : this->setValue(i, l, j, k, d[i][j][k][l]);
111 : }
112 31 : }
113 :
114 : /**
115 : * @brief Construct a new FloatTensor object
116 : * @param rhs TensorBase object to copy
117 : */
118 540296 : FloatTensor(TensorBase &rhs) : TensorBase(rhs) {}
119 :
120 : /**
121 : * @brief Basic Destructor
122 : */
123 1198347 : ~FloatTensor() {}
124 :
125 : /**
126 : * @brief Comparison operator overload
127 : * @param[in] rhs Tensor to be compared with
128 : * @note Only compares Tensor data
129 : */
130 : bool operator==(const FloatTensor &rhs) const;
131 :
132 : /**
133 : * @brief Comparison operator overload
134 : * @param[in] rhs Tensor to be compared with
135 : * @note Only compares Tensor data
136 : */
137 : bool operator!=(const FloatTensor &rhs) const { return !(*this == rhs); }
138 :
139 : /**
140 : * @copydoc Tensor::allocate()
141 : */
142 : void allocate() override;
143 :
144 : /**
145 : * @copydoc Tensor::deallocate()
146 : */
147 : void deallocate() override;
148 :
149 : /**
150 : * @copydoc Tensor::getData()
151 : */
152 : void *getData() const override;
153 :
154 : /**
155 : * @copydoc Tensor::getData(size_t idx)
156 : */
157 : void *getData(size_t idx) const override;
158 :
159 : /**
160 : * @brief i data index
161 : * @retval address of ith data
162 : */
163 : void *getAddress(unsigned int i) override;
164 :
165 : /**
166 : * @brief i data index
167 : * @retval address of ith data
168 : */
169 : const void *getAddress(unsigned int i) const override;
170 :
171 : /**
172 : * @brief return value at specific location
173 : * @param[in] i index
174 : */
175 : const float &getValue(unsigned int i) const;
176 :
177 : /**
178 : * @brief return value at specific location
179 : * @param[in] i index
180 : */
181 : float &getValue(unsigned int i);
182 :
183 : /**
184 : * @brief return value at specific location
185 : * @param[in] b batch location
186 : * @param[in] c channel location
187 : * @param[in] h height location
188 : * @param[in] w width location
189 : */
190 : const float &getValue(unsigned int b, unsigned int c, unsigned int h,
191 : unsigned int w) const;
192 :
193 : /**
194 : * @brief return value at specific location
195 : * @param[in] b batch location
196 : * @param[in] c channel location
197 : * @param[in] h height location
198 : * @param[in] w width location
199 : */
200 : float &getValue(unsigned int b, unsigned int c, unsigned int h,
201 : unsigned int w);
202 :
203 : /**
204 : * @copydoc Tensor::setValue(float value)
205 : */
206 : void setValue(float value) override;
207 :
208 : /**
209 : * @copydoc Tensor::setValue(b, c, h, w, value)
210 : */
211 : void setValue(unsigned int b, unsigned int c, unsigned int h, unsigned int w,
212 : float value) override;
213 :
214 : /**
215 : * @copydoc Tensor::addValue(b, c, h, w, value, beta)
216 : */
217 : void addValue(unsigned int b, unsigned int c, unsigned int h, unsigned int w,
218 : float value, float beta) override;
219 :
220 : /**
221 : * @copydoc Tensor::setZero()
222 : */
223 : void setZero() override;
224 :
225 : /**
226 : * @brief Set the Dist object
227 : * @param dist distribution engine
228 : */
229 18214 : template <typename Engine> void setDist(Engine dist) {
230 18214 : NNTR_THROW_IF(!contiguous, std::invalid_argument)
231 : // << getName() << " Tensor is not contiguous, cannot set distribution";
232 : << " Tensor is not contiguous, cannot set distribution";
233 :
234 18214 : float *data_ = (float *)getData();
235 18214 : unsigned int len = size();
236 73266601 : for (unsigned int i = 0; i < len; ++i) {
237 73248387 : data_[i] = (float)dist(rng);
238 : }
239 18214 : };
240 :
241 : /**
242 : * @copydoc Tensor::setRandNormal()
243 : */
244 : void setRandNormal(float mean = 0.0f, float stddev = 0.05f) override;
245 :
246 : /**
247 : * @copydoc Tensor::setRandUniform()
248 : */
249 : void setRandUniform(float min = -0.05f, float max = 0.05f) override;
250 :
251 : /**
252 : * @copydoc Tensor::setRandBernoulli()
253 : */
254 : void setRandBernoulli(float probability = 0.5f) override;
255 :
256 : /**
257 : * @copydoc Tensor::initialize()
258 : */
259 : void initialize() override;
260 :
261 : /**
262 : * @copydoc Tensor::initialize(Initializer init)
263 : */
264 : void initialize(Initializer init) override;
265 :
266 : /**
267 : * @copydoc Tensor::apply(std::function<T(T)> f, Tensor &output)
268 : */
269 : Tensor &apply(std::function<float(float)> f, Tensor &output) const override;
270 :
271 : /**
272 : * @copydoc Tensor::multiply_strided(Tensor const &m, Tensor &output,
273 : * const float beta)
274 : */
275 : Tensor multiply_strided(Tensor const &m, Tensor &output,
276 : const float beta) const override;
277 :
278 : /**
279 : * @copydoc Tensor::multiply_i(float const &value)
280 : */
281 : int multiply_i(float const &value) override;
282 :
283 : /**
284 : * @copydoc Tensor::multiply(float const &value, Tensor &out)
285 : */
286 : Tensor &multiply(float const &value, Tensor &out) const override;
287 :
288 : /**
289 : * @copydoc Tensor::multiply(Tensor const &m, Tensor &output, const
290 : * float beta = 0.0)
291 : */
292 : Tensor &multiply(Tensor const &m, Tensor &output,
293 : const float beta = 0.0) const override;
294 :
295 : /**
296 : * @copydoc Tensor::divide(float const &value, Tensor &output)
297 : */
298 : Tensor ÷(float const &value, Tensor &output) const override;
299 :
300 : /**
301 : * @copydoc Tensor::divide(Tensor const &m, Tensor &output)
302 : */
303 : Tensor ÷(Tensor const &m, Tensor &output) const override;
304 :
305 : /**
306 : * @copydoc Tensor::add_strided(Tensor const &input, Tensor &output,
307 : * const float beta)
308 : */
309 : Tensor &add_strided(Tensor const &input, Tensor &output,
310 : const float beta) const override;
311 :
312 : /**
313 : * @copydoc Tensor::add_i_partial()
314 : */
315 : int add_i_partial(unsigned int len, unsigned int addr_idx, Tensor &m,
316 : unsigned int incX, unsigned int incY, const Tensor alphas,
317 : unsigned int alpha_idx) override;
318 :
319 : /**
320 : * @copydoc Tensor::add(float const &value, Tensor &output)
321 : */
322 : Tensor &add(float const &value, Tensor &output) const override;
323 :
324 : /**
325 : * @copydoc Tensor::add(Tensor const &m, Tensor &output, float const
326 : * alpha)
327 : */
328 : Tensor &add(Tensor const &m, Tensor &output,
329 : float const alpha) const override;
330 :
331 : /**
332 : * @copydoc Tensor::subtract(float const &value, Tensor &output)
333 : */
334 : Tensor &subtract(float const &value, Tensor &output) const override;
335 :
336 : /**
337 : * @copydoc TensorBase::sum_by_batch(Tensor &output)
338 : */
339 : void sum_by_batch(Tensor &output) const override;
340 :
341 : /**
342 : * @copydoc Tensor::sum(unsigned int axis, Tensor &output, float alpha,
343 : * float beta) const
344 : */
345 : Tensor &sum(unsigned int axis, Tensor &output, float alpha,
346 : float beta) const override;
347 :
348 : /**
349 : * @copydoc Tensor::abs()
350 : */
351 : Tensor &abs(Tensor &output) const override;
352 :
353 : /**
354 : * @copydoc Tensor::l2norm
355 : */
356 : float l2norm() const override;
357 :
358 : /**
359 : * @copydoc Tensor::normalization_i
360 : */
361 : void normalization_i(unsigned int dim, float p = 2.0,
362 : float epsilon = 1e-12) override;
363 :
364 : /**
365 : * @copydoc Tensor::pow(float exponent, Tensor &output)
366 : */
367 : Tensor &pow(float exponent, Tensor &output) const override;
368 :
369 : /**
370 : * @copydoc Tensor::sqrt(&output)
371 : */
372 : Tensor &sqrt(Tensor &output) const override;
373 :
374 : /**
375 : * @copydoc Tensor::erf(Tensor &output)
376 : */
377 : Tensor &erf(Tensor &output) const override;
378 :
379 : /**
380 : * @copydoc Tensor::sin(Tensor &out, float alpha)
381 : */
382 : void sin(Tensor &out, float alpha) override;
383 :
384 : /**
385 : * @copydoc Tensor::cos(Tensor &out, float alpha)
386 : */
387 : void cos(Tensor &out, float alpha) override;
388 :
389 : /**
390 : * @copydoc Tensor::tan(Tensor &output, float alpha)
391 : */
392 : void tan(Tensor &output, float alpha) override;
393 :
394 : /**
395 : * @copydoc TensorBase::inv_sqrt(Tensor &out)
396 : */
397 : void inv_sqrt(Tensor &out) override;
398 :
399 : /**
400 : * @copydoc Tensor::dot(Tensor const &input, Tensor &output, bool
401 : * trans, bool trans_in, float beta)
402 : */
403 : Tensor &dot(Tensor const &input, Tensor &output, bool trans, bool trans_in,
404 : float beta) const override;
405 :
406 : void dot(std::vector<Tensor *> input, std::vector<Tensor *> output,
407 : bool trans, bool trans_in, float beta) const override;
408 :
409 : /**
410 : * @copydoc Tensor::dropout_mask(float dropout)
411 : */
412 : void dropout_mask(float dropout) override;
413 :
414 : /**
415 : * @copydoc Tensor::filter_mask(const Tensor &mask_len, bool reverse)
416 : */
417 : void filter_mask(const Tensor &mask_len, bool reverse) override;
418 :
419 : /**
420 : * @copydoc Tensor::zoneout_mask(Tensor &opposite, float zoneout)
421 : */
422 : void zoneout_mask(Tensor &opposite, float zoneout) override;
423 :
424 : /**
425 : * @copydoc Tensor::split(std::vector<size_t> sizes, int axis)
426 : */
427 : std::vector<Tensor> split(std::vector<size_t> sizes, int axis) override;
428 :
429 : /**
430 : * @copydoc Tensor::concat()
431 : */
432 : Tensor concat(const std::vector<Tensor> &tensors, int axis,
433 : Tensor &output) override;
434 :
435 : /**
436 : * @copydoc Tensor::copy(const Tensor &from)
437 : */
438 : void copy(const Tensor &from) override;
439 :
440 : /**
441 : * @copydoc Tensor::copyData(const Tensor &from)
442 : */
443 : void copyData(const Tensor &from) override;
444 :
445 : /**
446 : * @brief Copy the Tensor
447 : * @param[in] input Tensor to be copied
448 : * @param[out] output output Tensor
449 : */
450 : void copy_with_stride(const Tensor &input, Tensor &output) override;
451 :
452 : /**
453 : * @copydoc Tensor::argmax()
454 : */
455 : std::vector<unsigned int> argmax() const override;
456 :
457 : /**
458 : * @copydoc Tensor::argmin()
459 : */
460 : std::vector<unsigned int> argmin() const override;
461 :
462 : /**
463 : * @copydoc TensorBase::top_k()
464 : */
465 : void topK(unsigned int k, void *output_data, uint32_t *indices) override;
466 :
467 : /**
468 : * @copydoc Tensor::max_abs()
469 : */
470 : float max_abs() const override;
471 : /**
472 : * @copydoc Tensor::maxValue()
473 : */
474 : float maxValue() const override;
475 :
476 : /**
477 : * @copydoc Tensor::minValue()
478 : */
479 : float minValue() const override;
480 :
481 : /**
482 : * @copydoc Tensor::transpose(const std::string &direction, Tensor &out)
483 : */
484 : Tensor &transpose(const std::string &direction,
485 : Tensor &output) const override;
486 :
487 : /**
488 : * @copydoc Tensor::print(std::ostream &out)
489 : */
490 : void print(std::ostream &out) const override;
491 :
492 : private:
493 : /**
494 : * @brief copy a buffer to @a this, the caller has to ensure that @a this is
495 : * initialized otherwise undefined behavior
496 : *
497 : * @param buf buffer to copy from
498 : */
499 : void copy(const void *buf);
500 :
501 : /**
502 : * @brief Applies the given operator to the tensor with the passed argument
503 : * @param[in] m Tensor
504 : * @param[in] v_func vectorized function to apply
505 : * @param e broadcast info.
506 : * @param cur_axis current axis. pass default when calling outside.
507 : * @param offset offset for this. pass default when calling outside.
508 : * @param m_offset offset for m. pass default when calling outside.
509 : * @retval #ML_ERROR_NONE Successful
510 : * @retval #ML_ERROR_INVALID_PARAMETER Invalid Parameter
511 : */
512 : void
513 : apply_broadcast_util(Tensor const &m,
514 : std::function<void(const BroadcastInfo &e, const float *,
515 : const float *, float *)>
516 : v_func,
517 : Tensor &output, const BroadcastInfo &e,
518 : int cur_axis = -1, size_t offset = 0,
519 : size_t m_offset = 0) const;
520 :
521 : /**
522 : * @brief Applies the given operator to the tensor with the passed argument
523 : *
524 : * @param[in] m Tensor
525 : * @param[in] v_func vectorized function to apply
526 : * @retval #ML_ERROR_NONE Successful
527 : * @retval #ML_ERROR_INVALID_PARAMETER Invalid Parameter
528 : */
529 : void apply_broadcast(Tensor const &m,
530 : std::function<void(const BroadcastInfo &e, const float *,
531 : const float *, float *)>
532 : v_func,
533 : Tensor &output) const;
534 :
535 : /**
536 : * @brief Get the Data Type String object
537 : * @return std::string of tensor data type (FP32)
538 : */
539 1 : std::string getStringDataType() const override { return "FP32"; }
540 :
541 : /**
542 : * @copydoc Tensor::isValid()
543 : */
544 : bool isValid() const override;
545 :
546 : /**
547 : * @brief Float.dot(Float)
548 : * @return Tensor& reference to the output tensor
549 : */
550 : Tensor &dotFloat(Tensor const &input, Tensor &output, bool trans,
551 : bool trans_in, float beta) const;
552 :
553 : /**
554 : * @brief Float32.dot(Float16)
555 : * @return Tensor& reference to the output tensor
556 : */
557 : Tensor &dotFloat32Float16(Tensor const &input, Tensor &output, bool trans,
558 : bool trans_in, float beta) const;
559 :
560 : /**
561 : * @brief Float.dot(Q4K/Q6K)
562 : * @return Tensor& reference to the output tensor
563 : */
564 : Tensor &dotQnK(Tensor const &input, Tensor &output, bool trans, bool trans_in,
565 : float beta, Tdatatype dtype) const;
566 :
567 : /**
568 : * @brief Float.dot(QINT4/QINT8/QINT16)
569 : * @return Tensor& reference to the output tensor
570 : */
571 : Tensor &dotQInteger(Tensor const &input, Tensor &output, bool trans,
572 : bool trans_in, float beta, Tdatatype dtype) const;
573 : };
574 :
575 : } // namespace nntrainer
576 :
577 : #endif /* __cplusplus */
578 : #endif /* __FLOAT_TENSOR_H__ */
|