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/nnstreamer/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 1198342 : ~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::pow(float exponent, Tensor &output)
360 : */
361 : Tensor &pow(float exponent, Tensor &output) const override;
362 :
363 : /**
364 : * @copydoc Tensor::sqrt(&output)
365 : */
366 : Tensor &sqrt(Tensor &output) const override;
367 :
368 : /**
369 : * @copydoc Tensor::erf(Tensor &output)
370 : */
371 : Tensor &erf(Tensor &output) const override;
372 :
373 : /**
374 : * @copydoc Tensor::sin(Tensor &out, float alpha)
375 : */
376 : void sin(Tensor &out, float alpha) override;
377 :
378 : /**
379 : * @copydoc Tensor::cos(Tensor &out, float alpha)
380 : */
381 : void cos(Tensor &out, float alpha) override;
382 :
383 : /**
384 : * @copydoc Tensor::tan(Tensor &output, float alpha)
385 : */
386 : void tan(Tensor &output, float alpha) override;
387 :
388 : /**
389 : * @copydoc TensorBase::inv_sqrt(Tensor &out)
390 : */
391 : void inv_sqrt(Tensor &out) override;
392 :
393 : /**
394 : * @copydoc Tensor::dot(Tensor const &input, Tensor &output, bool
395 : * trans, bool trans_in, float beta)
396 : */
397 : Tensor &dot(Tensor const &input, Tensor &output, bool trans, bool trans_in,
398 : float beta) const override;
399 :
400 : void dot(std::vector<Tensor *> input, std::vector<Tensor *> output,
401 : bool trans, bool trans_in, float beta) const override;
402 :
403 : /**
404 : * @copydoc Tensor::dropout_mask(float dropout)
405 : */
406 : void dropout_mask(float dropout) override;
407 :
408 : /**
409 : * @copydoc Tensor::filter_mask(const Tensor &mask_len, bool reverse)
410 : */
411 : void filter_mask(const Tensor &mask_len, bool reverse) override;
412 :
413 : /**
414 : * @copydoc Tensor::zoneout_mask(Tensor &opposite, float zoneout)
415 : */
416 : void zoneout_mask(Tensor &opposite, float zoneout) override;
417 :
418 : /**
419 : * @copydoc Tensor::split(std::vector<size_t> sizes, int axis)
420 : */
421 : std::vector<Tensor> split(std::vector<size_t> sizes, int axis) override;
422 :
423 : /**
424 : * @copydoc Tensor::concat()
425 : */
426 : Tensor concat(const std::vector<Tensor> &tensors, int axis,
427 : Tensor &output) override;
428 :
429 : /**
430 : * @copydoc Tensor::copy(const Tensor &from)
431 : */
432 : void copy(const Tensor &from) override;
433 :
434 : /**
435 : * @copydoc Tensor::copyData(const Tensor &from)
436 : */
437 : void copyData(const Tensor &from) override;
438 :
439 : /**
440 : * @brief Copy the Tensor
441 : * @param[in] input Tensor to be copied
442 : * @param[out] output output Tensor
443 : */
444 : void copy_with_stride(const Tensor &input, Tensor &output) override;
445 :
446 : /**
447 : * @copydoc Tensor::argmax()
448 : */
449 : std::vector<unsigned int> argmax() const override;
450 :
451 : /**
452 : * @copydoc Tensor::argmin()
453 : */
454 : std::vector<unsigned int> argmin() const override;
455 :
456 : /**
457 : * @copydoc TensorBase::top_k()
458 : */
459 : void topK(unsigned int k, void *output_data, uint32_t *indices) override;
460 :
461 : /**
462 : * @copydoc Tensor::max_abs()
463 : */
464 : float max_abs() const override;
465 : /**
466 : * @copydoc Tensor::maxValue()
467 : */
468 : float maxValue() const override;
469 :
470 : /**
471 : * @copydoc Tensor::minValue()
472 : */
473 : float minValue() const override;
474 :
475 : /**
476 : * @copydoc Tensor::transpose(const std::string &direction, Tensor &out)
477 : */
478 : Tensor &transpose(const std::string &direction,
479 : Tensor &output) const override;
480 :
481 : /**
482 : * @copydoc Tensor::print(std::ostream &out)
483 : */
484 : void print(std::ostream &out) const override;
485 :
486 : private:
487 : /**
488 : * @brief copy a buffer to @a this, the caller has to ensure that @a this is
489 : * initialized otherwise undefined behavior
490 : *
491 : * @param buf buffer to copy from
492 : */
493 : void copy(const void *buf);
494 :
495 : /**
496 : * @brief Applies the given operator to the tensor with the passed argument
497 : * @param[in] m Tensor
498 : * @param[in] v_func vectorized function to apply
499 : * @param e broadcast info.
500 : * @param cur_axis current axis. pass default when calling outside.
501 : * @param offset offset for this. pass default when calling outside.
502 : * @param m_offset offset for m. pass default when calling outside.
503 : * @retval #ML_ERROR_NONE Successful
504 : * @retval #ML_ERROR_INVALID_PARAMETER Invalid Parameter
505 : */
506 : void
507 : apply_broadcast_util(Tensor const &m,
508 : std::function<void(const BroadcastInfo &e, const float *,
509 : const float *, float *)>
510 : v_func,
511 : Tensor &output, const BroadcastInfo &e,
512 : int cur_axis = -1, size_t offset = 0,
513 : size_t m_offset = 0) const;
514 :
515 : /**
516 : * @brief Applies the given operator to the tensor with the passed argument
517 : *
518 : * @param[in] m Tensor
519 : * @param[in] v_func vectorized function to apply
520 : * @retval #ML_ERROR_NONE Successful
521 : * @retval #ML_ERROR_INVALID_PARAMETER Invalid Parameter
522 : */
523 : void apply_broadcast(Tensor const &m,
524 : std::function<void(const BroadcastInfo &e, const float *,
525 : const float *, float *)>
526 : v_func,
527 : Tensor &output) const;
528 :
529 : /**
530 : * @brief Get the Data Type String object
531 : * @return std::string of tensor data type (FP32)
532 : */
533 1 : std::string getStringDataType() const override { return "FP32"; }
534 :
535 : /**
536 : * @copydoc Tensor::isValid()
537 : */
538 : bool isValid() const override;
539 :
540 : /**
541 : * @brief Float.dot(Float)
542 : * @return Tensor& reference to the output tensor
543 : */
544 : Tensor &dotFloat(Tensor const &input, Tensor &output, bool trans,
545 : bool trans_in, float beta) const;
546 :
547 : /**
548 : * @brief Float32.dot(Float16)
549 : * @return Tensor& reference to the output tensor
550 : */
551 : Tensor &dotFloat32Float16(Tensor const &input, Tensor &output, bool trans,
552 : bool trans_in, float beta) const;
553 :
554 : /**
555 : * @brief Float.dot(Q4K/Q6K)
556 : * @return Tensor& reference to the output tensor
557 : */
558 : Tensor &dotQnK(Tensor const &input, Tensor &output, bool trans, bool trans_in,
559 : float beta, Tdatatype dtype) const;
560 :
561 : /**
562 : * @brief Float.dot(QINT4/QINT8/QINT16)
563 : * @return Tensor& reference to the output tensor
564 : */
565 : Tensor &dotQInteger(Tensor const &input, Tensor &output, bool trans,
566 : bool trans_in, float beta, Tdatatype dtype) const;
567 : };
568 :
569 : } // namespace nntrainer
570 :
571 : #endif /* __cplusplus */
572 : #endif /* __FLOAT_TENSOR_H__ */
|