LCOV - code coverage report
Current view: top level - nntrainer/tensor - tensor_base.h (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 66.7 % 72 48
Test Date: 2025-12-14 20:38:17 Functions: 45.0 % 20 9

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : /**
       3              :  * @file        tensor_base.h
       4              :  * @date        01 December 2023
       5              :  * @brief       This is Tensor base class
       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 __TENSOR_BASE_H__
      13              : #define __TENSOR_BASE_H__
      14              : #ifdef __cplusplus
      15              : 
      16              : #include <memory>
      17              : #include <stdexcept>
      18              : 
      19              : #include <memory_data.h>
      20              : #include <nntrainer_error.h>
      21              : #include <quantizer.h>
      22              : #include <tensor_dim.h>
      23              : #include <util_func.h>
      24              : 
      25              : #define transposeloop(cl, ci, cj, ck, sl, si, sj, sk)                          \
      26              :   do {                                                                         \
      27              :     unsigned int i, j, k, l;                                                   \
      28              :     int inidx = 0, outidx = 0;                                                 \
      29              :     for (cl = 0; cl < sl; cl++)                                                \
      30              :       for (ci = 0; ci < si; ci++)                                              \
      31              :         for (cj = 0; cj < sj; cj++)                                            \
      32              :           for (ck = 0; ck < sk; ck++) {                                        \
      33              :             outidx = si * sj * sk * cl + sj * sk * ci + sk * cj + ck;          \
      34              :             inidx = l * SI * SJ * SK + i * SJ * SK + j * SK + k;               \
      35              :             outptr[outidx] = inptr[inidx];                                     \
      36              :           }                                                                    \
      37              :   } while (0);
      38              : 
      39              : #define transposeloop_nhwc(cl, ci, cj, ck, sl, si, sj, sk)                     \
      40              :   do {                                                                         \
      41              :     unsigned int i, j, k, l;                                                   \
      42              :     int inidx = 0, outidx = 0;                                                 \
      43              :     for (cl = 0; cl < sl; cl++)                                                \
      44              :       for (ci = 0; ci < si; ci++)                                              \
      45              :         for (cj = 0; cj < sj; cj++)                                            \
      46              :           for (ck = 0; ck < sk; ck++) {                                        \
      47              :             outidx = si * sj * sk * cl + sj * sk * ci + sk * cj + ck;          \
      48              :             inidx = l * SJ * SK * SI + j * SK * SI + k * SI + i;               \
      49              :             outptr[outidx] = inptr[inidx];                                     \
      50              :           }                                                                    \
      51              :   } while (0);
      52              : 
      53              : namespace nntrainer {
      54              : 
      55              : using TensorDim = ml::train::TensorDim;
      56              : using Tformat = ml::train::TensorDim::Format;
      57              : using Tdatatype = ml::train::TensorDim::DataType;
      58              : using TStorageOrder = ml::train::TensorDim::StorageOrder;
      59              : 
      60              : /**
      61              :  * @brief     Enumeration of Weight Initialization Type
      62              :  * @todo      support intialization from file
      63              :  */
      64              : enum class Initializer {
      65              :   ZEROS,          /** Zero initialization */
      66              :   ONES,           /** One initialization */
      67              :   LECUN_NORMAL,   /** LeCun normal initialization */
      68              :   LECUN_UNIFORM,  /** uniform initialization */
      69              :   XAVIER_NORMAL,  /** Xavier normal initialization */
      70              :   XAVIER_UNIFORM, /** Xavier uniform initialization */
      71              :   HE_NORMAL,      /** He normal initialization */
      72              :   HE_UNIFORM,     /** He uniform initialization */
      73              :   NONE            /** No initialization */
      74              : };
      75              : 
      76              : class Tensor;
      77              : class SrcSharedTensorBase;
      78              : 
      79              : /**
      80              :  * @class TensorBase class
      81              :  * @brief TensorBase is an abstract class that provides a base for various
      82              :  * tensor classes with different data types such as FloatTensor to extend and
      83              :  * implement abstract methods.
      84              :  *
      85              :  * @note Basic functions required for tensor memory allocation and data
      86              :  * modification, such as allocate(), getData(), and setValue(), are necessary
      87              :  * when creating subclasses (new tensor class).
      88              :  *
      89              :  * The remaining operations that are used for mathematical operations are not
      90              :  * essential to create a new tensor class but later should be implemented in a
      91              :  * child class in order to utilize its tensor operations fully.
      92              :  */
      93              : class TensorBase {
      94              : public:
      95              :   /**
      96              :    * @brief     Basic Constructor of Tensor
      97              :    */
      98       658324 :   TensorBase(std::string name_ = "", Tformat fm = Tformat::NCHW,
      99       658324 :              Tdatatype d_type = Tdatatype::FP32) :
     100      1316648 :     dim(TensorDim(fm, d_type)),
     101       658324 :     strides(dim.computeStrides()),
     102       658324 :     contiguous(true),
     103       658324 :     initializer(Initializer::NONE),
     104       658324 :     name(name_),
     105              :     data(nullptr),
     106       658324 :     offset(0),
     107       658324 :     file_offset(0),
     108       658324 :     src_tensor() {}
     109              : 
     110              :   /**
     111              :    * @brief     Constructor of Tensor with dimension, possibly lazily
     112              :    * @param d Tensor dim for this tensor
     113              :    * @param alloc_now If the memory of the tensor must be allocated
     114              :    * @param init Initializer for the tensor
     115              :    * @param name Name of the tensor
     116              :    */
     117              :   TensorBase(const TensorDim &d, bool alloc_now,
     118              :              Initializer init = Initializer::NONE, std::string name = "");
     119              : 
     120              :   /**
     121              :    * @brief     Constructor of Tensor with dimension/buf
     122              :    * @param d Tensor dim for this tensor
     123              :    * @param buf buffer
     124              :    * @note Memory for this tensor is instantaneously allocated
     125              :    */
     126              :   TensorBase(const TensorDim &d, const void *buf = nullptr) :
     127              :     TensorBase(d, true) {}
     128              : 
     129              :   /**
     130              :    *  @brief  Copy constructor of TensorBase.
     131              :    *  @param[in] Tensor &
     132              :    */
     133       540310 :   TensorBase(const TensorBase &rhs) {
     134       540310 :     dim = rhs.dim;
     135       540310 :     strides = rhs.strides;
     136       540310 :     contiguous = rhs.contiguous;
     137       540310 :     initializer = rhs.initializer;
     138       540310 :     name = rhs.name;
     139              :     data = rhs.data;
     140       540310 :     offset = rhs.offset;
     141       540310 :     file_offset = rhs.file_offset;
     142              :     src_tensor = rhs.src_tensor;
     143       540310 :   }
     144              : 
     145              :   /**
     146              :    * @brief     Comparison operator overload
     147              :    * @param[in] rhs Tensor to be compared with
     148              :    * @note      Only compares Tensor information
     149              :    */
     150              :   bool operator==(const TensorBase &rhs) const;
     151              : 
     152              :   /**
     153              :    * @brief     Comparison operator overload
     154              :    * @param[in] rhs Tensor to be compared with
     155              :    * @note      Only compares Tensor information
     156              :    */
     157              :   bool operator!=(const TensorBase &rhs) const { return !(*this == rhs); }
     158              : 
     159              :   /**
     160              :    * @copydoc Tensor::setTensorVar(TensorDim d, void *buf, size_t offset)
     161              :    */
     162              :   void setTensorVar(TensorDim d, void *buf, size_t offset);
     163              : 
     164              :   /**
     165              :    * @brief Basic Destructor
     166              :    */
     167      2397068 :   virtual ~TensorBase() {}
     168              : 
     169              :   /**
     170              :    * @copydoc Tensor::allocate()
     171              :    */
     172              :   virtual void allocate() = 0;
     173              : 
     174              :   /**
     175              :    * @copydoc Tensor::deallocate()
     176              :    */
     177              :   virtual void deallocate() = 0;
     178              : 
     179              :   /**
     180              :    * @copydoc Tensor::isAllocated()
     181              :    */
     182              :   bool isAllocated() { return data != nullptr; }
     183              : 
     184              :   /**
     185              :    * @brief activate function with the given pointer address
     186              :    * @note This should be called for virtual tensor only.
     187              :    */
     188            0 :   void activate(void *addr) {
     189            0 :     data = std::shared_ptr<MemoryData>(new MemoryData((void *)addr));
     190            0 :   }
     191              : 
     192              :   /**
     193              :    * @brief deactivate
     194              :    * @note This should be called for virtual tensor only.
     195              :    */
     196            0 :   void deactivate() {
     197              :     data.reset();
     198              :     data = nullptr;
     199            0 :   }
     200              : 
     201              :   /**
     202              :    * @copydoc Tensor::getData()
     203              :    */
     204              :   virtual void *getData() const = 0;
     205              : 
     206              :   /**
     207              :    * @copydoc Tensor::getData(size_t idx)
     208              :    */
     209              :   virtual void *getData(size_t idx) const = 0;
     210              : 
     211              :   /**
     212              :    * @copydoc Tensor::getScale()
     213              :    */
     214            1 :   virtual void *getScale() const {
     215              :     throw std::invalid_argument(
     216            1 :       "Tensor::getScale() is not supported in tensor data type " +
     217            3 :       getStringDataType());
     218              :   }
     219              : 
     220              :   /**
     221              :    * @copydoc Tensor::getScale(size_t idx)
     222              :    */
     223            0 :   virtual void *getScale(size_t idx) const {
     224              :     throw std::invalid_argument(
     225            0 :       "Tensor::getScale() is not supported in tensor data type " +
     226            0 :       getStringDataType());
     227              :   }
     228              : 
     229              :   /**
     230              :    * @copydoc Tensor::getZeroPoint()
     231              :    */
     232            0 :   virtual unsigned int *getZeroPoint() const {
     233              :     throw std::invalid_argument(
     234            0 :       "Tensor::getZeroPoint() is not supported in tensor data type " +
     235            0 :       getStringDataType());
     236              :   }
     237              : 
     238              :   /**
     239              :    * @copydoc Tensor::getZeroPoint(size_t idx)
     240              :    */
     241            0 :   virtual unsigned int *getZeroPoint(size_t idx) const {
     242              :     throw std::invalid_argument(
     243            0 :       "Tensor::getZeroPoint() is not supported in tensor data type " +
     244            0 :       getStringDataType());
     245              :   }
     246              : 
     247              :   /**
     248              :    * @brief     i data index
     249              :    * @retval    address of ith data
     250              :    */
     251              :   virtual void *getAddress(unsigned int i) = 0;
     252              : 
     253              :   /**
     254              :    * @brief     i data index
     255              :    * @retval    address of ith data
     256              :    */
     257              :   virtual const void *getAddress(unsigned int i) const = 0;
     258              : 
     259              :   /**
     260              :    * @copydoc Tensor::setValue(float value)
     261              :    */
     262              :   virtual void setValue(float value) = 0;
     263              : 
     264              :   /**
     265              :    * @copydoc Tensor::setValue(b, c, h, w, value)
     266              :    */
     267              :   virtual void setValue(unsigned int b, unsigned int c, unsigned int h,
     268              :                         unsigned int w, float value) = 0;
     269              : 
     270              :   /**
     271              :    * @copydoc Tensor::addValue()
     272              :    */
     273              :   virtual void addValue(unsigned int b, unsigned int c, unsigned int h,
     274              :                         unsigned int w, float value, float beta) = 0;
     275              : 
     276              :   /**
     277              :    * @copydoc Tensor::setZero()
     278              :    */
     279              :   virtual void setZero() = 0;
     280              : 
     281              :   /**
     282              :    * @copydoc Tensor::setRandNormal()
     283              :    */
     284              :   virtual void setRandNormal(float mean, float stddev);
     285              : 
     286              :   /**
     287              :    * @copydoc Tensor::setRandBernoulli()
     288              :    */
     289              :   virtual void setRandUniform(float min, float max);
     290              : 
     291              :   /**
     292              :    * @copydoc Tensor::setRandBernoulli()
     293              :    */
     294              :   virtual void setRandBernoulli(float probability);
     295              : 
     296              :   /**
     297              :    * @copydoc Tensor::initialize()
     298              :    */
     299              :   virtual void initialize() = 0;
     300              : 
     301              :   /**
     302              :    * @copydoc Tensor::initialize(Initializer init)
     303              :    */
     304              :   virtual void initialize(Initializer init) = 0;
     305              : 
     306              :   /**
     307              :    * @copydoc Tensor::multiply_strided(Tensor const &m, Tensor &output,
     308              :    * const float beta)
     309              :    */
     310              :   virtual Tensor multiply_strided(Tensor const &m, Tensor &output,
     311              :                                   const float beta) const;
     312              : 
     313              :   /**
     314              :    * @copydoc Tensor::multiply_i(float const &value)
     315              :    */
     316              :   virtual int multiply_i(float const &value);
     317              : 
     318              :   /**
     319              :    * @copydoc Tensor::multiply(float const &value, Tensor &output)
     320              :    */
     321              :   virtual Tensor &multiply(float const &value, Tensor &output) const;
     322              : 
     323              :   /**
     324              :    * @copydoc Tensor::multiply(Tensor const &m, Tensor &output, const
     325              :    * float beta = 0.0)
     326              :    */
     327              :   virtual Tensor &multiply(Tensor const &m, Tensor &output,
     328              :                            const float beta = 0.0) const;
     329              : 
     330              :   /**
     331              :    * @copydoc Tensor::divide(float const &value, Tensor &output)
     332              :    */
     333              :   virtual Tensor &divide(float const &value, Tensor &output) const;
     334              : 
     335              :   /**
     336              :    * @copydoc Tensor::divide(Tensor const &m, Tensor &output)
     337              :    */
     338              :   virtual Tensor &divide(Tensor const &m, Tensor &output) const;
     339              : 
     340              :   /**
     341              :    * @copydoc Tensor::add_strided(Tensor const &input, Tensor &output,
     342              :    * const float beta)
     343              :    */
     344              :   virtual Tensor &add_strided(Tensor const &input, Tensor &output,
     345              :                               const float beta) const;
     346              : 
     347              :   /**
     348              :    * @copydoc Tensor::add_i_partial()
     349              :    */
     350              :   virtual int add_i_partial(unsigned int len, unsigned int addr_idx, Tensor &m,
     351              :                             unsigned int incX, unsigned int incY,
     352              :                             const Tensor alphas, unsigned int alpha_idx);
     353              : 
     354              :   /**
     355              :    * @copydoc Tensor::add(float const &value, Tensor &output)
     356              :    */
     357              :   virtual Tensor &add(float const &value, Tensor &output) const;
     358              : 
     359              :   /**
     360              :    * @copydoc Tensor::add(Tensor const &m, Tensor &output, float const
     361              :    * alpha)
     362              :    */
     363              :   virtual Tensor &add(Tensor const &m, Tensor &output, float const alpha) const;
     364              : 
     365              :   /**
     366              :    * @copydoc Tensor::subtract(float const &value, Tensor &output)
     367              :    */
     368              :   virtual Tensor &subtract(float const &value, Tensor &output) const;
     369              : 
     370              :   /**
     371              :    * @brief      Sum all the Tensor elements according to the batch
     372              :    * @param[out] output Tensor(batch, 1, 1, 1)
     373              :    */
     374              :   virtual void sum_by_batch(Tensor &output) const;
     375              : 
     376              :   /**
     377              :    * @copydoc Tensor::sum(unsigned int axis, Tensor &output, float alpha,
     378              :    * float beta) const
     379              :    */
     380              :   virtual Tensor &sum(unsigned int axis, Tensor &output, float alpha,
     381              :                       float beta) const;
     382              : 
     383              :   /**
     384              :    * @copydoc Tensor::abs()
     385              :    */
     386              :   virtual Tensor &abs(Tensor &output) const;
     387              : 
     388              :   /**
     389              :    * @copydoc Tensor::l2norm
     390              :    */
     391              :   virtual float l2norm() const;
     392              : 
     393              :   /**
     394              :    * @copydoc Tensor::pow(float exponent, Tensor &output)
     395              :    */
     396              :   virtual Tensor &pow(float exponent, Tensor &output) const;
     397              : 
     398              :   /**
     399              :    * @copydoc Tensor::sqrt(Tensor &output)
     400              :    */
     401              :   virtual Tensor &sqrt(Tensor &output) const;
     402              : 
     403              :   /**
     404              :    * @copydoc Tensor::erf(Tensor &output)
     405              :    */
     406              :   virtual Tensor &erf(Tensor &output) const;
     407              : 
     408              :   /**
     409              :    * @brief    sin transform function
     410              :    * @param[out] out out to store the result
     411              :    */
     412              :   virtual void sin(Tensor &out, float alpha = 1.0);
     413              : 
     414              :   /**
     415              :    * @brief    cos transform function
     416              :    * @param[out] out out to store the result
     417              :    */
     418              :   virtual void cos(Tensor &out, float alpha = 1.0);
     419              : 
     420              :   /**
     421              :    * @brief    tangent transform function
     422              :    * @param[out] output output to store the result
     423              :    */
     424              :   virtual void tan(Tensor &output, float alpha = 1.0);
     425              : 
     426              :   /**
     427              :    * @brief      inverse squared root function
     428              :    * @param[out] out out to store the result
     429              :    */
     430              :   virtual void inv_sqrt(Tensor &out);
     431              : 
     432              :   /**
     433              :    * @brief     Dot Product of Tensor ( equal MxM )
     434              :    * @details   This applies dot of the last dimension of this and
     435              :    * second-last dimension of passed tensor m.
     436              :    * @param[in] input Tensor
     437              :    * @param[in] output output Tensor
     438              :    * @param[in] trans Transpose
     439              :    * @param[in] trans_in Transpose input
     440              :    * @param[in] beta beta
     441              :    * @retval    Calculated Tensor
     442              :    */
     443              :   virtual Tensor &dot(Tensor const &input, Tensor &output, bool trans,
     444              :                       bool trans_in, float beta) const;
     445              : 
     446              :   /**
     447              :    * @brief     Dot Product of Tensors ( equal MxMs )
     448              :    * @details   This applies dot of the last dimension of this and
     449              :    * second-last dimension of passed tensor m.
     450              :    * @param[in] input Tensor
     451              :    * @param[in] output output Tensors
     452              :    * @param[in] trans Transpose
     453              :    * @param[in] trans_in Transpose input
     454              :    * @param[in] beta beta
     455              :    * @retval    Calculated Tensor
     456              :    */
     457              :   virtual void dot(std::vector<Tensor *> input, std::vector<Tensor *> output,
     458              :                    bool trans, bool trans_in, float beta) const;
     459              : 
     460              :   /**
     461              :    * @copydoc Tensor::dropout_mask(float dropout)
     462              :    */
     463              :   virtual void dropout_mask(float dropout);
     464              : 
     465              :   /**
     466              :    * @copydoc Tensor::filter_mask(const Tensor &mask_len, bool reverse)
     467              :    */
     468              :   virtual void filter_mask(const Tensor &mask_len, bool reverse);
     469              : 
     470              :   /**
     471              :    * @copydoc Tensor::zoneout_mask(Tensor &opposite, float zoneout)
     472              :    */
     473              :   virtual void zoneout_mask(Tensor &opposite, float zoneout);
     474              : 
     475              :   /**
     476              :    * @copydoc Tensor::split(std::vector<size_t> sizes, int axis)
     477              :    */
     478              :   virtual std::vector<Tensor> split(std::vector<size_t> sizes, int axis);
     479              : 
     480              :   /**
     481              :    * @copydoc Tensor::concat()
     482              :    */
     483              :   virtual Tensor concat(const std::vector<Tensor> &tensors, int axis,
     484              :                         Tensor &output);
     485              : 
     486              :   /**
     487              :    * @copydoc Tensor::print(std::ostream &out)
     488              :    */
     489              :   virtual void print(std::ostream &out) const = 0;
     490              : 
     491              :   /**
     492              :    * @copydoc Tensor::apply(std::function<T(T)> f, Tensor &output)
     493              :    * @note    This will be only used in FloatTensor.
     494              :    */
     495              :   virtual Tensor &apply(std::function<float(float)> f, Tensor &output) const;
     496              : 
     497              : #ifdef ENABLE_FP16
     498              :   /**
     499              :    * @copydoc Tensor::apply(std::function<T(T)> f, Tensor &output)
     500              :    * @note    This will be only used in HalfTensor.
     501              :    */
     502              :   virtual Tensor &apply(std::function<_FP16(_FP16)> f, Tensor &output) const;
     503              : #endif
     504              : 
     505              :   /**
     506              :    * @brief     Copy the Tensor
     507              :    * @param[in] from Tensor to be copied
     508              :    *
     509              :    * @note copy can reshape the tensor to match the shape
     510              :    */
     511              :   virtual void copy(const Tensor &from) = 0;
     512              : 
     513              :   /**
     514              :    * @brief     Copy the Tensor
     515              :    * @param[in] from Tensor to be copied
     516              :    */
     517              :   virtual void copyData(const Tensor &from) = 0;
     518              : 
     519              :   /**
     520              :    * @brief      Copy the Tensor
     521              :    * @param[in]  input Tensor to be copied
     522              :    * @param[out] output output Tensor
     523              :    */
     524              :   virtual void copy_with_stride(const Tensor &input, Tensor &output) = 0;
     525              : 
     526              :   /**
     527              :    * @brief     Save the Tensor into file
     528              :    * @param[in] file input file stream
     529              :    */
     530              :   virtual void save(std::ostream &file);
     531              : 
     532              :   /**
     533              :    * @brief     Read the Tensor from file
     534              :    * @param[in] file input file stream
     535              :    */
     536              :   virtual void read(std::ifstream &file, size_t start_offset = 0,
     537              :                     bool read_from_offset = false);
     538              : 
     539              :   /**
     540              :    * @brief     Read the Tensor from file
     541              :    * @param[in] file input file stream
     542              :    */
     543              :   virtual void read(ReadSource src, size_t start_offset = 0,
     544              :                     bool read_from_offset = false);
     545              : 
     546              :   /**
     547              :    * @copydoc Tensor::readFSU()
     548              :    */
     549              :   virtual void readFSU();
     550              : 
     551              :   /**
     552              :    * @copydoc Tensor::argmax()
     553              :    */
     554              :   virtual std::vector<unsigned int> argmax() const;
     555              : 
     556              :   /**
     557              :    * @copydoc Tensor::argmin()
     558              :    */
     559              :   virtual std::vector<unsigned int> argmin() const;
     560              : 
     561              :   /**
     562              :    * @brief Compute top-K maximum values along the width dimension
     563              :    *
     564              :    * @details This function computes the top-K maximum values and their
     565              :    * corresponding indices along the **width** dimension for each batch,
     566              :    * channel, and height slice. The operation preserves the original tensor
     567              :    * format (NCHW/NHWC) while reducing the width dimension to size K. The
     568              :    * indices are stored in the provided `indices` array, and the top-K values
     569              :    *          are stored in the provided `output_data` buffer.
     570              :    *
     571              :    * @param[in] k Number of largest elements to select (1 <= k <= width_size)
     572              :    * @param[out] output_data Buffer to store top-K values (must be
     573              :    * pre-allocated)
     574              :    * @param[out] indices Array to store corresponding indices (must be
     575              :    * pre-allocated)
     576              :    *
     577              :    * @throw std::invalid_argument If:
     578              :    *         - k is 0 or exceeds width dimension size
     579              :    *         - Called on non-floating point tensor (UINT8/UINT16/etc)
     580              :    */
     581              :   virtual void topK(unsigned int k, void *output_data, uint32_t *indices);
     582              : 
     583              :   /**
     584              :    * @copydoc Tensor::max_abs()
     585              :    */
     586              :   virtual float max_abs() const = 0;
     587              : 
     588              :   /**
     589              :    * @copydoc Tensor::maxValue()
     590              :    */
     591              :   virtual float maxValue() const = 0;
     592              : 
     593              :   /**
     594              :    * @copydoc Tensor::minValue()
     595              :    */
     596              :   virtual float minValue() const = 0;
     597              : 
     598              :   /**
     599              :    * @copydoc Tensor::transpose(const std::string &direction, Tensor &out)
     600              :    */
     601              :   virtual Tensor &transpose(const std::string &direction, Tensor &out) const;
     602              : 
     603              :   /**
     604              :    * @brief     put data of Tensor
     605              :    * @note      It is only effective when fsu is used
     606              :    */
     607              :   void putData() const;
     608              : 
     609              :   /**
     610              :    * @brief Set the memory buffer for the tensor
     611              :    * @param buf the memory buffer
     612              :    * @param off offset
     613              :    */
     614              :   void setMemoryData(const std::shared_ptr<MemoryData> buf, size_t off);
     615              : 
     616              :   /**
     617              :    * @brief     return Data pointer of Tensor
     618              :    * @retval    template T pointer (float pointer as default)
     619              :    */
     620              :   const std::shared_ptr<MemoryData> getMemoryData() const;
     621              : 
     622              :   /**
     623              :    * @brief     return offset
     624              :    */
     625              :   size_t getOffset() const;
     626              : 
     627              :   /**
     628              :    * @brief     get FileOffset of Tensor
     629              :    * @return    size_t fileOffset
     630              :    */
     631              :   size_t getFileOffset() const;
     632              : 
     633              :   /**
     634              :    * @brief     set FileOffset to Tensor
     635              :    * @param     off FileOffset
     636              :    */
     637              :   void setFileOffset(size_t off);
     638              : 
     639              :   /**
     640              :    * @brief     set Tensor Dim
     641              :    * @param[in] d TensorDim
     642              :    * @note      Throws std::invalid_argument if size mismatch
     643              :    */
     644              :   void reshape(const TensorDim &d);
     645              : 
     646              :   /**
     647              :    * @brief     return a copy of the Tensor Dim
     648              :    * @retval    TensorDim
     649              :    */
     650        25046 :   TensorDim getDim() const { return TensorDim(dim); }
     651              : 
     652              :   /**
     653              :    * @brief     return Tensor Type
     654              :    */
     655              :   TensorDim::TensorType getTensorType() const { return dim.getTensorType(); }
     656              : 
     657              :   /**
     658              :    * @brief Get initializer for the tensor
     659              :    * @retval initializer of the tensor
     660              :    */
     661         1434 :   Initializer getInitializer() const { return initializer; }
     662              : 
     663              :   /**
     664              :    * @brief Get format for the tensor
     665              :    * @retval format of the tensor
     666              :    */
     667              :   TensorDim::Format getFormat() const { return dim.getFormat(); }
     668              : 
     669              :   /**
     670              :    * @brief Get data type for the tensor
     671              :    * @retval data type of the tensor
     672              :    */
     673              :   Tdatatype getDataType() const { return dim.getDataType(); }
     674              : 
     675              :   /**
     676              :    * @brief     update batch size for this tensor
     677              :    * @param     batch size
     678              :    */
     679              :   void updateBatch(unsigned int batch);
     680              : 
     681              :   /**
     682              :    * @brief     update the dimension for this tensor
     683              :    * @param     dimension dimension to be updated
     684              :    */
     685              :   void updateDimension(TensorDim dimension);
     686              : 
     687              :   /**
     688              :    * @brief     return whether tensor is contiguous or not.
     689              :    * @retval    bool contiguous
     690              :    */
     691       110616 :   const bool getContiguous() const noexcept { return contiguous; }
     692              : 
     693              :   /**
     694              :    * @brief     return current stride of tensor.
     695              :    * @retval    int[MAXDIM] strides
     696              :    */
     697              :   const std::array<size_t, TensorDim::MAXDIM> getStrides() const noexcept {
     698        81265 :     return strides;
     699              :   }
     700              : 
     701              :   /**
     702              :    * @brief     Set name of the tensor
     703              :    */
     704         1199 :   void setName(const std::string &name_) { name = name_; }
     705              : 
     706              :   /**
     707              :    * @brief     Get name of the tensor
     708              :    * @retval    string name
     709              :    */
     710        85744 :   const std::string &getName() const { return name; }
     711              : 
     712              :   /**
     713              :    * @brief Get linear index given the n-d index
     714              :    */
     715              :   size_t getIndex(unsigned int b, unsigned int c, unsigned int h,
     716              :                   unsigned int w) const noexcept;
     717              : 
     718              :   /**
     719              :    * @brief     Save quantization information
     720              :    */
     721            0 :   virtual void save_quantization_info(std::ostream &file) {}
     722              : 
     723              :   /**
     724              :    * @brief     Read quantization information
     725              :    */
     726            0 :   virtual void read_quantization_info(std::ifstream &file,
     727              :                                       size_t start_offset = 0,
     728            0 :                                       bool read_from_offset = false) {}
     729              : 
     730              :   /**
     731              :    * @brief     Read quantization information
     732              :    */
     733            0 :   virtual void read_quantization_info(ReadSource src, size_t start_offset = 0,
     734            0 :                                       bool read_from_offset = false) {}
     735              : 
     736              :   /**
     737              :    * @brief     Get size of current tensor
     738              :    * @retval    unsigned int size of the current tensor
     739              :    */
     740     25131290 :   virtual size_t size() const { return dim.getDataLen(); }
     741              : 
     742              :   /**
     743              :    * @brief     Get if the tensor is empty
     744              :    * @retval    true if the tensor is empty
     745              :    */
     746      1649179 :   bool empty() const { return size() == 0; }
     747              : 
     748              :   /**
     749              :    * @brief     Get size of the data in bytes
     750              :    * @retval    size_t Size in bytes
     751              :    */
     752        25465 :   size_t bytes() const { return size() * dim.getDataTypeSize(); }
     753              : 
     754              :   /**
     755              :    * @brief     Get a total size of the memory data in bytes
     756              :    * @retval    size_t Size in bytes
     757              :    */
     758        38180 :   virtual size_t getMemoryBytes() const {
     759        38180 :     return size() * dim.getDataTypeSize();
     760              :   }
     761              : 
     762              :   /**
     763              :    * @brief     return Tensor batch size
     764              :    * @retval    batch size
     765              :    */
     766      5779517 :   size_t batch() const { return dim.batch(); }
     767              : 
     768              :   /**
     769              :    * @brief     return Tensor channel size
     770              :    * @retval    channel size
     771              :    */
     772      5734476 :   size_t channel() const { return dim.channel(); }
     773              : 
     774              :   /**
     775              :    * @brief     return Tensor height size
     776              :    * @retval    height size
     777              :    */
     778      5987775 :   size_t height() const { return dim.height(); }
     779              : 
     780              :   /**
     781              :    * @brief     return Tensor width size
     782              :    * @retval    width size
     783              :    */
     784      6113976 :   size_t width() const { return dim.width(); }
     785              : 
     786              :   /**
     787              :    * @brief     return Tensor scale factor size if exists
     788              :    * @retval    scale factor size
     789              :    * @note      Override for quantize tensor
     790              :    */
     791       169008 :   virtual size_t scale_size() const { return 0; }
     792              : 
     793              :   /**
     794              :    * @brief     return Tensor quantization scheme
     795              :    * @retval    Qscheme qscheme
     796              :    * @note      Override for quantize tensor
     797              :    */
     798            0 :   virtual QScheme q_scheme() const {
     799              :     throw std::invalid_argument(
     800            0 :       "Tensor::q_scheme() is not supported in tensor data type " +
     801            0 :       getStringDataType());
     802              :   }
     803              : 
     804              :   /**
     805              :    * @brief Merge the given two axis for tensor at second axis inplace
     806              :    *
     807              :    * @param axis1 first axis to merge
     808              :    * @param axis2 second axis to merge
     809              :    */
     810              :   void mergeAxis(unsigned int axis1, unsigned int axis2);
     811              : 
     812              :   /**
     813              :    * @brief Allocate data based on the source tensor
     814              :    * @note As this memory is shared, do NOT initialize
     815              :    */
     816              :   void allocateSrcTensor();
     817              : 
     818              :   /**
     819              :    * @brief Update destination tensor to share memory with source tensor
     820              :    *
     821              :    * @param src src tensor containing the memory
     822              :    * @param dest destination tensor which will share the memory
     823              :    * @param offset offset to be used from the start of the data in bytes
     824              :    * @note The new tensor will share the same data as the current tensor but
     825              :    * can have different size.
     826              :    * @note New size added with offset must be less than the size of the original
     827              :    * tensor.
     828              :    */
     829              :   void createSharedDataTensor(const TensorBase *src, TensorBase *dest,
     830              :                               size_t offset) const;
     831              : 
     832              :   /**
     833              :    * @brief Get new tensor which shares memory with current tensor but different
     834              :    * shape
     835              :    *
     836              :    * @param[in] dim new dimension to be set for this tensor
     837              :    * @param[in] offset offset to be used from the start of the data in elements
     838              :    * @param[in] reset_stride reset stride
     839              :    * @param[in] name_ name of the Tensor
     840              :    * @param[out] ret output TensorBase pointer
     841              :    * @note The new tensor will share the same data as the current tensor but
     842              :    * can have different size.
     843              :    * @note New size added with offset must be less than the size of the original
     844              :    * tensor.
     845              :    */
     846              :   void getSharedDataTensor(const TensorDim dim_, size_t offset,
     847              :                            bool reset_stride, const std::string &name_,
     848              :                            TensorBase *ret);
     849              : 
     850              :   /**
     851              :    * @copydoc Tensor::isValid()
     852              :    */
     853              :   virtual bool isValid() const = 0;
     854              : 
     855              :   static constexpr float epsilon = 1e-5f;
     856              : 
     857              : protected:
     858              :   TensorDim dim;
     859              :   std::array<size_t, TensorDim::MAXDIM> strides;
     860              :   bool contiguous;
     861              :   Initializer initializer;
     862              :   std::string name; /**< name of the tensor */
     863              :   std::shared_ptr<MemoryData> data;
     864              :   size_t offset;
     865              :   size_t file_offset; /**< offset of the tensor in the file */
     866              : 
     867              :   /**<
     868              :    * When using shared_data with tensor, this stores the ptr of the source
     869              :    * tensor which handles the full memory. If tensor data is already allocated,
     870              :    * this does not affect the tensor. If the tensor data is not allocated, and
     871              :    * src_ptr is valid, this tensor will use the memory allocated by the src_ptr
     872              :    */
     873              :   std::shared_ptr<SrcSharedTensorBase> src_tensor;
     874              : 
     875              :   /**
     876              :    * @struct External Loop Info for broadcasted info
     877              :    * @brief External Loop Info for broadcasted iteration. Please refer to
     878              :    * DISABLED_private_external_loop_n in unittest_nntrainer_tensor.
     879              :    * @note This should better be implemented in iterator fashion before used
     880              :    * extensively.
     881              :    */
     882              :   struct BroadcastInfo {
     883              : 
     884              :     /**
     885              :      * @brief Construct a new External Loop Info object
     886              :      */
     887              :     BroadcastInfo() :
     888        76768 :       buffer_size(0),
     889        76768 :       buffer_axis(-1),
     890        76768 :       strides{0, 0, 0, 0},
     891              :       tensor_type({Tformat::NCHW, Tdatatype::FP32}) {}
     892              : 
     893              :     unsigned int buffer_size; /**< virtual size of the buffer */
     894              :     int buffer_axis;          /**< the smallest axis that should be looped.
     895              :                                    -1 means no loop needed*/
     896              :     std::array<unsigned int, TensorDim::MAXDIM>
     897              :       strides; /**< modified strides for the loop */
     898              :     nntrainer::TensorDim::TensorType tensor_type;
     899              :   };
     900              : 
     901              :   /**
     902              :    * @brief compute Loop info for broadcasting and vectorization
     903              :    *
     904              :    * @param m target tensor to be calculated against.
     905              :    * @return BroadcastInfo Loopinfo needed to run external loop
     906              :    */
     907              :   BroadcastInfo computeBroadcastInfo(const Tensor &m) const;
     908              : 
     909              :   /**
     910              :    * @brief Calcuates variables needed to perform tensor flatten dot product
     911              :    *
     912              :    * @param[in]  input Tensor
     913              :    * @param[in]  output output Tensor
     914              :    * @param[in]  trans Transpose
     915              :    * @param[in]  trans_in Transpose input
     916              :    * @param[out] first_three_flat flattened the fist 3 axis
     917              :    * @param[out] last_axis last axis
     918              :    * @param[out] input_first_three_flat input's flattened the fist 3 axis
     919              :    * @param[out] input_last_axis input's last axis
     920              :    * @param[out] M number of op(this)'s and output's row
     921              :    * @param[out] N number of op(inputs)'s and output's columns
     922              :    * @param[out] K number of op(this)'s column and op(input)'s row
     923              :    * @param[out] lda leading dimension of this
     924              :    * @param[out] ldb leading dimension of input
     925              :    * @param[out] ldc leading dimension of output
     926              :    *
     927              :    * @note op(X) is one of X or X**T
     928              :    */
     929              :   void calculateFlattenDot(Tensor const &input, Tensor &output, bool trans,
     930              :                            bool trans_in, unsigned int &first_three_flat,
     931              :                            unsigned int &last_axis,
     932              :                            unsigned int &input_first_three_flat,
     933              :                            unsigned int &input_last_axis, unsigned int &M,
     934              :                            unsigned int &N, unsigned int &K, unsigned int &lda,
     935              :                            unsigned int &ldb, unsigned int &ldc) const;
     936              : 
     937              :   /**
     938              :    * @brief  Get the Data Type String object
     939              :    * @return std::string of tensor data type
     940              :    * @note   TensorBase::getStringDataType() should not be called. Please define
     941              :    * this function in the derived class to the corresponding data type.
     942              :    */
     943            0 :   virtual std::string getStringDataType() const { return "Undefined type"; }
     944              : };
     945              : 
     946              : /**
     947              :  * @class SrcSharedTensorBase
     948              :  * @brief Source of the shared tensor
     949              :  */
     950              : class SrcSharedTensorBase {
     951              : public:
     952              :   /**
     953              :    * @brief   Constructor for the class
     954              :    */
     955              :   SrcSharedTensorBase() : src(nullptr), off(0) {}
     956              : 
     957              :   /**
     958              :    * @brief   Constructor for the class
     959              :    */
     960       301854 :   SrcSharedTensorBase(const TensorBase *tensor, size_t offset) :
     961       301854 :     src(tensor), off(offset) {}
     962              : 
     963              :   /**
     964              :    * @brief   Get the allocated src tensor
     965              :    */
     966       603708 :   const TensorBase *tensor() const {
     967       603708 :     if (!src)
     968            0 :       throw std::runtime_error("Accessing empty src tensor");
     969              : 
     970       603708 :     return src;
     971              :   }
     972              : 
     973              :   /**
     974              :    * @brief   Get the offset from the source tensor
     975              :    */
     976       301854 :   size_t offset() const { return off; }
     977              : 
     978              : private:
     979              :   const TensorBase *src; /**< Tensor of the source */
     980              :   size_t off;            /**< offset from the source data ptr */
     981              : };
     982              : 
     983              : } // namespace nntrainer
     984              : 
     985              : #endif /* __cplusplus */
     986              : #endif /* __TENSOR_BASE_H__ */
        

Generated by: LCOV version 2.0-1