LCOV - code coverage report
Current view: top level - nntrainer/tensor - var_grad.h (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 84.2 % 57 48
Test Date: 2025-12-14 20:38:17 Functions: 80.0 % 10 8

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : /**
       3              :  * Copyright (C) 2020 Parichay Kapoor <pk.kapoor@samsung.com>
       4              :  *
       5              :  * @file   var_grad.h
       6              :  * @date   13 November 2020
       7              :  * @see    https://github.com/nnstreamer/nntrainer
       8              :  * @author Parichay Kapoor <pk.kapoor@samsung.com>
       9              :  * @bug    No known bugs except for NYI items
      10              :  * @brief  This is Var_Grad Class for Neural Network
      11              :  *
      12              :  */
      13              : 
      14              : #ifndef __VAR_GRAD_H__
      15              : #define __VAR_GRAD_H__
      16              : 
      17              : #include <tuple>
      18              : 
      19              : #include <tensor.h>
      20              : #include <tensor_wrap_specs.h>
      21              : 
      22              : namespace nntrainer {
      23              : 
      24              : /**
      25              :  * @class   Var_Grad
      26              :  * @brief   Variable with Gradient, and its corresponding need_gradient property
      27              :  */
      28              : class Var_Grad {
      29              : public:
      30              :   /**
      31              :    * @brief Specification of the Var_Grad
      32              :    *
      33              :    * @details The tuple values are dimension, need_gradient property, and the
      34              :    * name of the Var_Grad object.
      35              :    */
      36              :   typedef VarGradSpec Spec;
      37              : 
      38              :   /**
      39              :    * @brief Var_Grad default constructor
      40              :    * @note Default variable is not need_gradient as gradient is 0 dim tensor
      41              :    */
      42            1 :   Var_Grad() : Var_Grad(TensorDim()) {}
      43              : 
      44              :   /**
      45              :    * @brief Var_Grad default destructor
      46              :    */
      47        41839 :   virtual ~Var_Grad() = default;
      48              : 
      49              :   /**
      50              :    * @brief Construct a new Var_Grad object
      51              :    *
      52              :    * @param dim Variable and gradient tensor dimension
      53              :    * @param ng If the variable is need_gradient
      54              :    * @param alloc_now The memory for the var_grad tensors be allocated upon init
      55              :    * @param name Name for this Var_Grad
      56              :    */
      57              :   explicit Var_Grad(const TensorDim &dim,
      58              :                     const Initializer init = Initializer::NONE, bool ng = true,
      59              :                     bool alloc_now = false, const std::string &name = "");
      60              : 
      61              :   /**
      62              :    * @brief Construct a new Var_Grad object
      63              :    *
      64              :    * @param dim_v Variable tensor dimension
      65              :    * @param dim_g Gradient tensor dimension
      66              :    * @param ng If the variable is need_gradient
      67              :    * @param alloc_now The memory for the var_grad tensors be allocated upon init
      68              :    * @param name Name for this Var_Grad
      69              :    */
      70              :   explicit Var_Grad(const TensorDim &dim_v, const TensorDim &dim_g,
      71              :                     const Initializer init = Initializer::NONE, bool ng = true,
      72              :                     bool alloc_now = false, const std::string &name = "");
      73              : 
      74              :   /**
      75              :    * @brief Construct a new Var_Grad object
      76              :    *
      77              :    * @param spec Var_Grad specification
      78              :    */
      79          166 :   explicit Var_Grad(const Spec &spec, bool alloc_now = false) :
      80              :     Var_Grad(std::get<0>(spec), // TensorDim
      81              :              std::get<1>(spec), // initializer
      82          166 :              std::get<2>(spec), // need_gradient
      83              :              alloc_now,
      84              :              std::get<3>(spec) // Name
      85          166 :     ) {}
      86              : 
      87              :   /**
      88              :    * @brief Construct a new Var_Grad object
      89              :    *
      90              :    * @param v Already created variable object
      91              :    * @param g Already created gradient object
      92              :    * @param n Name for this Var_Grad
      93              :    * @param is_dependent true if the var grad is dependent
      94              :    *
      95              :    * @note This API is not recommended for usage and must be used for internal
      96              :    * uses only, as Var_Grad does not own the tensors v and g, and can go invalid
      97              :    * if the owner of these tensors free the tensors.
      98              :    */
      99         4184 :   explicit Var_Grad(const Tensor &v, const Tensor &g, const std::string &n = "",
     100         4184 :                     bool is_dependent = false) :
     101         4184 :     is_dependent(is_dependent),
     102         4184 :     is_first_access_gradient(false),
     103         4184 :     is_last_access_gradient(false),
     104              :     var(
     105         8368 :       std::make_shared<Tensor>(v.getSharedDataTensor(v.getDim(), 0, false, n))),
     106         8368 :     grad(std::make_shared<Tensor>(n + grad_suffix)) {
     107         4184 :     if (!g.empty())
     108         3992 :       grad = std::make_shared<Tensor>(
     109        11976 :         g.getSharedDataTensor(v.getDim(), 0, false, n + grad_suffix));
     110         4184 :   }
     111              : 
     112              :   /**
     113              :    * @brief Construct a new Var_Grad object
     114              :    *
     115              :    * @param v ptr to already created variable tensor
     116              :    * @param g ptr to already created gradient tensor
     117              :    * @param is_dependent true if the given var grad is dependent
     118              :    */
     119        18389 :   explicit Var_Grad(Tensor *v, Tensor *g, bool is_dependent = false) :
     120        18389 :     is_dependent(is_dependent),
     121        18389 :     is_first_access_gradient(false),
     122        18389 :     is_last_access_gradient(false),
     123              :     var(std::shared_ptr<Tensor>(v, [](void *) {})),
     124        18389 :     grad(std::shared_ptr<Tensor>(g, [](void *) {})) {
     125        18389 :     if (!v)
     126            0 :       var = std::make_shared<Tensor>();
     127        18389 :     if (!g)
     128         1718 :       grad = std::make_shared<Tensor>();
     129        18389 :   }
     130              : 
     131              :   /**
     132              :    * @brief Copy constructor for Var_Grad
     133              :    *
     134              :    * @param rhs Var_Grad to construct from
     135              :    */
     136         1822 :   Var_Grad(const Var_Grad &rhs) = default;
     137              : 
     138              :   /**
     139              :    * @brief Move constructor for Var_Grad
     140              :    *
     141              :    * @param rhs Var_Grad to construct from
     142              :    */
     143         3234 :   Var_Grad(Var_Grad &&rhs) = default;
     144              : 
     145              :   /**
     146              :    * @brief copy assigment
     147              :    *
     148              :    * @param rhs copy from
     149              :    * @return Var_Grad& Updated Var_Grad
     150              :    */
     151              :   Var_Grad &operator=(const Var_Grad &rhs) = default;
     152              : 
     153              :   /**
     154              :    * @brief move assignment
     155              :    *
     156              :    * @param rhs move from
     157              :    * @return Var_Grad& Updated Var_Grad
     158              :    */
     159            0 :   Var_Grad &operator=(Var_Grad &&rhs) = default;
     160              : 
     161              :   /**
     162              :    * @brief Initialize the variable
     163              :    * @param preallocated if initialized, use this tensor for variable memory
     164              :    */
     165              :   virtual void initializeVariable(const Tensor &preallocated = Tensor());
     166              : 
     167              :   /**
     168              :    * @brief Initialize the gradient for the variable
     169              :    * @param preallocated if initialized, use this tensor for gradient memory
     170              :    */
     171              :   virtual void initializeGradient(const Tensor &preallocated = Tensor());
     172              : 
     173              :   /**
     174              :    * @brief Get the TensorDim
     175              :    *
     176              :    * @return TensorDim Dimension
     177              :    */
     178        10867 :   TensorDim getDim() const { return var->getDim(); }
     179              : 
     180              :   /**
     181              :    * @brief Get the name of the variable
     182              :    *
     183              :    * @return std::string name of the variable
     184              :    */
     185        14358 :   const std::string &getName() const { return var->getName(); }
     186              : 
     187              :   /**
     188              :    * @brief Get the name of the gradient
     189              :    *
     190              :    * @return std::string name of the gradient
     191              :    */
     192          994 :   const std::string &getGradientName() const { return grad->getName(); }
     193              : 
     194              :   /**
     195              :    * @brief Get the variable tensor
     196              :    *
     197              :    * @return Tensor Variable tensor
     198              :    */
     199         6903 :   Tensor getVariable() const { return *var.get(); }
     200              : 
     201              :   /**
     202              :    * @brief Get the Gradient tensor
     203              :    *
     204              :    * @return Tensor Gradient tensor
     205              :    */
     206         2302 :   Tensor getGradient() const { return *grad.get(); }
     207              : 
     208              :   /**
     209              :    * @brief Reset the gradient to 0
     210              :    */
     211              :   void resetGradient() {
     212              :     /** zero the gradient */
     213              :     grad->initialize();
     214              :   }
     215              : 
     216              :   /**
     217              :    * @brief Set batch size
     218              :    *
     219              :    * @param batch batch size
     220              :    */
     221         9156 :   void setBatchSize(unsigned int batch) {
     222         9156 :     if (!var->empty())
     223         9156 :       var->updateBatch(batch);
     224         9156 :     if (grad && !grad->empty())
     225         8208 :       grad->updateBatch(batch);
     226         9156 :   }
     227              : 
     228              :   /**
     229              :    * @brief Update the dimension
     230              :    *
     231              :    * @param dimension dimension to be updated
     232              :    */
     233            0 :   void updateDimension(TensorDim dimension) {
     234            0 :     if (!var->empty())
     235            0 :       var->updateDimension(dimension);
     236            0 :     if (grad && !grad->empty())
     237            0 :       grad->updateDimension(dimension);
     238            0 :   }
     239              : 
     240              :   /**
     241              :    * @brief Get the variable tensor (by reference)
     242              :    *
     243              :    * @return Tensor Variable tensor
     244              :    */
     245              :   Tensor &getVariableRef() { return *var.get(); }
     246              : 
     247              :   /**
     248              :    * @brief Get the Gradient tensor (by reference)
     249              :    *
     250              :    * @return Tensor Gradient tensor
     251              :    */
     252              :   Tensor &getGradientRef() { return *grad.get(); }
     253              : 
     254              :   /**
     255              :    * @brief Get the variable tensor (by reference)
     256              :    *
     257              :    * @return Tensor Variable tensor
     258              :    */
     259              :   const Tensor &getVariableRef() const { return *var.get(); }
     260              : 
     261              :   /**
     262              :    * @brief Get the Gradient tensor (by reference)
     263              :    *
     264              :    * @return Tensor Gradient tensor
     265              :    */
     266              :   const Tensor &getGradientRef() const { return *grad.get(); }
     267              : 
     268              :   /**
     269              :    * @brief If this variable has gradient
     270              :    *
     271              :    * @return true if the var_grad as gradient set, else false
     272              :    * @note this is can return is the var_grad needs gradient but it not
     273              :    * empty
     274              :    */
     275       129624 :   bool hasGradient() const {
     276       129624 :     if (!grad)
     277              :       return false;
     278       129624 :     if (var->isAllocated())
     279       103569 :       return grad->isAllocated();
     280        26055 :     return !grad->empty();
     281              :   }
     282              : 
     283              :   /**
     284              :    * @brief check if given weight is dependent to other weight
     285              :    *
     286              :    * @return bool return true if the weight is dependent to others
     287              :    */
     288            0 :   bool isDependent() const { return is_dependent; }
     289              : 
     290              :   /**
     291              :    * @brief Set the As First Gradient Access
     292              :    *
     293              :    */
     294         4036 :   void setAsGradientFirstAccess() { is_first_access_gradient = true; }
     295              : 
     296              :   /**
     297              :    * @brief Set the As Gradient Last Access object
     298              :    *
     299              :    */
     300         4028 :   void setAsGradientLastAccess() { is_last_access_gradient = true; }
     301              : 
     302              :   /**
     303              :    * @brief check if given weight at the last execution order
     304              :    * (first access of gradient)
     305              :    *
     306              :    * @return bool true if last access
     307              :    */
     308        16248 :   bool isGradientFirstAccess() const { return is_first_access_gradient; }
     309              : 
     310              :   /**
     311              :    * @brief check if given weight at the first execution order (last access of
     312              :    * gradient)
     313              :    *
     314              :    * @return bool true if last access
     315              :    */
     316        28654 :   bool isGradientLastAccess() const { return is_last_access_gradient; }
     317              : 
     318              :   /**
     319              :    * @brief Get the norm of the gradient
     320              :    *
     321              :    * @return float l2 norm of the gradient
     322              :    */
     323           44 :   float getGradientNorm() const { return grad->l2norm(); }
     324              : 
     325              :   static constexpr const char *grad_suffix = ":grad";
     326              : 
     327              : protected:
     328              :   bool is_dependent; /**< check if the weight tensor is burrowed from somewhere
     329              :                         thus it is dependent */
     330              :   bool is_first_access_gradient; /**< check if current weight tensor is first
     331              :                                     access */
     332              :   bool is_last_access_gradient;  /**< check if current weight tensor is last
     333              :    access */
     334              : 
     335              :   std::shared_ptr<Tensor> var;  /**< variable to be updated and used */
     336              :   std::shared_ptr<Tensor> grad; /**< gradient for the variable */
     337              : };
     338              : 
     339              : } // namespace nntrainer
     340              : 
     341              : #endif /** __VAR_GRAD_H__ */
        

Generated by: LCOV version 2.0-1