LCOV - code coverage report
Current view: top level - nntrainer - engine.h (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 85.0 % 40 34
Test Date: 2025-12-14 20:38:17 Functions: 100.0 % 10 10

            Line data    Source code
       1              : // SPDX-License-Identifier: Apache-2.0
       2              : /**
       3              :  * Copyright (C) 2024 Jijoong Moon <jijoong.moon@samsung.com>
       4              :  *
       5              :  * @file   engine.h
       6              :  * @date   27 December 2024
       7              :  * @brief  This file contains engine context related functions and classes that
       8              :  * manages the engines (NPU, GPU, CPU) of the current environment
       9              :  * @see    https://github.com/nnstreamer/nntrainer
      10              :  * @author Jijoong Moon <jijoong.moon@samsung.com>
      11              :  * @bug    No known bugs except for NYI items
      12              :  *
      13              :  */
      14              : 
      15              : #ifndef __ENGINE_H__
      16              : #define __ENGINE_H__
      17              : 
      18              : #include <algorithm>
      19              : #include <functional>
      20              : #include <memory>
      21              : #include <mutex>
      22              : #include <sstream>
      23              : #include <stdexcept>
      24              : #include <string>
      25              : #include <type_traits>
      26              : #include <unordered_map>
      27              : #include <vector>
      28              : 
      29              : #include <context.h>
      30              : #include <mem_allocator.h>
      31              : #include <nntrainer_error.h>
      32              : 
      33              : #ifdef ENABLE_OPENCL
      34              : #include <cl_context.h>
      35              : #endif
      36              : 
      37              : #include "singleton.h"
      38              : 
      39              : namespace nntrainer {
      40              : 
      41              : extern std::mutex engine_mutex;
      42              : namespace {} // namespace
      43              : 
      44              : /**
      45              :  * @class Engine contains user-dependent configuration
      46              :  * @brief App
      47              :  */
      48              : class Engine : public Singleton<Engine> {
      49              : protected:
      50              :   static const int RegisterContextMax = 16;
      51              :   static nntrainer::Context *nntrainerRegisteredContext[RegisterContextMax];
      52              :   /// Valgrind complains memory leaks with context registered because
      53              :   /// every context is alive during the whole application lifecycle
      54              :   /// and we do not free them. It can be amended by using unique_ptr;
      55              :   /// however, as we use container and function calls with context,
      56              :   /// let's not bother modify all the related functions, but waste
      57              :   /// a few words.
      58              : 
      59              :   void initialize() noexcept override;
      60              : 
      61              :   void add_default_object();
      62              : 
      63           27 :   void registerContext(std::string name, nntrainer::Context *context) {
      64              :     const std::lock_guard<std::mutex> lock(engine_mutex);
      65              :     static int registerCount = 0;
      66              : 
      67              :     std::transform(name.begin(), name.end(), name.begin(),
      68           81 :                    [](unsigned char c) { return std::tolower(c); });
      69              : 
      70           27 :     if (engines.find(name) != engines.end()) {
      71            0 :       std::stringstream ss;
      72              :       ss << "Cannot register Context with name : " << name;
      73            0 :       throw std::invalid_argument(ss.str().c_str());
      74            0 :     }
      75            0 :     engines.insert(std::make_pair(name, context));
      76              : 
      77           27 :     if (registerCount < RegisterContextMax) {
      78           27 :       nntrainerRegisteredContext[registerCount] = context;
      79           27 :       registerCount++;
      80              :     }
      81              : 
      82           27 :     auto alloc = context->getMemAllocator();
      83              : 
      84           27 :     allocator.insert(std::make_pair(name, alloc));
      85           27 :   }
      86              : 
      87              : public:
      88              :   /**
      89              :    * @brief   Default constructor
      90              :    */
      91          693 :   Engine() = default;
      92              : 
      93              :   /**
      94              :    * @brief   Default Destructor
      95              :    */
      96         1359 :   ~Engine() = default;
      97              : 
      98              :   /**
      99              :    * @brief register a Context from a shared library
     100              :    * plugin must have **extern "C" LayerPluggable *ml_train_context_pluggable**
     101              :    * defined else error
     102              :    *
     103              :    * @param library_path a file name of the library
     104              :    * @param base_path    base path to make a full path (optional)
     105              :    * @throws std::invalid_parameter if library_path is invalid or library is
     106              :    * invalid
     107              :    */
     108              :   int registerContext(const std::string &library_path,
     109              :                       const std::string &base_path = "");
     110              : 
     111              :   /**
     112              :    * @brief get registered a Context
     113              :    *
     114              :    * @param name Registered Context Name
     115              :    * @throws std::invalid_parameter if no context with name
     116              :    * @return Context Pointer : for register Object factory, casting might be
     117              :    * needed.
     118              :    */
     119        11594 :   nntrainer::Context *getRegisteredContext(std::string name) const {
     120              : 
     121              :     std::transform(name.begin(), name.end(), name.begin(),
     122        34782 :                    [](unsigned char c) { return std::tolower(c); });
     123              : 
     124        11594 :     if (engines.find(name) == engines.end()) {
     125            0 :       throw std::invalid_argument("[Engine] " + name +
     126            0 :                                   " Context is not registered");
     127              :     }
     128        11594 :     return engines.at(name);
     129              :   }
     130              : 
     131              :   std::unordered_map<std::string, std::shared_ptr<nntrainer::MemAllocator>>
     132              :   getAllocators() {
     133              :     return allocator;
     134              :   }
     135              : 
     136              :   /**
     137              :    *
     138              :    * @brief Parse compute Engine keywords in properties : eg) engine = cpu
     139              :    *  default is "cpu"
     140              :    * @return Context name
     141              :    */
     142              :   std::string parseComputeEngine(const std::vector<std::string> &props) const;
     143              : 
     144              :   /**
     145              :    * @brief Create an Layer Object with Layer name
     146              :    *
     147              :    * @param type layer name
     148              :    * @param props property
     149              :    * @return unitque_ptr<T> unique pointer to the Layer object
     150              :    */
     151              :   std::unique_ptr<nntrainer::Layer>
     152         6126 :   createLayerObject(const std::string &type,
     153              :                     const std::vector<std::string> &properties = {}) const {
     154         6126 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     155         6126 :     return ct->createLayerObject(type);
     156              :   }
     157              : 
     158              :   /**
     159              :    * @brief Create an Layer Object with Layer key
     160              :    *
     161              :    * @param int_key key
     162              :    * @param props property
     163              :    * @return unitque_ptr<T> unique pointer to the Layer object
     164              :    */
     165              :   std::unique_ptr<nntrainer::Layer>
     166           91 :   createLayerObject(const int int_key,
     167              :                     const std::vector<std::string> &properties = {}) const {
     168           91 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     169           91 :     return ct->createLayerObject(int_key);
     170              :   }
     171              : 
     172              :   /**
     173              :    * @brief Create an Optimizer Object with Optimizer name
     174              :    *
     175              :    * @param type Optimizer name
     176              :    * @param props property
     177              :    * @return unitque_ptr<T> unique pointer to the Optimizer object
     178              :    */
     179              :   std::unique_ptr<nntrainer::Optimizer>
     180          743 :   createOptimizerObject(const std::string &type,
     181              :                         const std::vector<std::string> &properties = {}) const {
     182          743 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     183          743 :     return ct->createOptimizerObject(type);
     184              :   }
     185              : 
     186              :   /**
     187              :    * @brief Create an Optimizer Object with Optimizer key
     188              :    *
     189              :    * @param int_key key
     190              :    * @param props property
     191              :    * @return unitque_ptr<T> unique pointer to the Optimizer object
     192              :    */
     193              :   std::unique_ptr<nntrainer::Optimizer>
     194           29 :   createOptimizerObject(const int int_key,
     195              :                         const std::vector<std::string> &properties = {}) const {
     196           29 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     197           29 :     return ct->createOptimizerObject(int_key);
     198              :   }
     199              : 
     200              :   /**
     201              :    * @brief Create an LearningRateScheduler Object with type
     202              :    *
     203              :    * @param type type of LearningRateScheduler
     204              :    * @param props property
     205              :    * @return unitque_ptr<T> unique pointer to the LearningRateScheduler object
     206              :    */
     207              :   std::unique_ptr<ml::train::LearningRateScheduler>
     208           54 :   createLearningRateSchedulerObject(
     209              :     const std::string &type,
     210              :     const std::vector<std::string> &properties = {}) const {
     211           54 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     212           54 :     return ct->createLearningRateSchedulerObject(type, properties);
     213              :   }
     214              : 
     215              :   /**
     216              :    * @brief Create an LearningRateScheduler Object with key
     217              :    *
     218              :    * @param int_key key
     219              :    * @param props property
     220              :    * @return unitque_ptr<T> unique pointer to the LearningRateScheduler object
     221              :    */
     222              :   std::unique_ptr<ml::train::LearningRateScheduler>
     223           22 :   createLearningRateSchedulerObject(
     224              :     const int int_key, const std::vector<std::string> &properties = {}) {
     225           22 :     auto ct = getRegisteredContext(parseComputeEngine(properties));
     226           22 :     return ct->createLearningRateSchedulerObject(int_key, properties);
     227              :   }
     228              : 
     229              :   /**
     230              :    * @brief Get Working Path from a relative or representation of a path
     231              :    * starting from @a working_path_base.
     232              :    * @param[in] path to make full path
     233              :    * @return If absolute path is given, returns @a path
     234              :    * If relative path is given and working_path_base is not set, return
     235              :    * relative path.
     236              :    * If relative path is given and working_path_base has set, return absolute
     237              :    * path from current working directory
     238              :    */
     239              :   const std::string getWorkingPath(const std::string &path = "") const;
     240              : 
     241              :   /**
     242              :    * @brief Set Working Directory for a relative path. working directory is set
     243              :    * canonically
     244              :    * @param[in] base base directory
     245              :    * @throw std::invalid_argument if path is not valid for current system
     246              :    */
     247              :   void setWorkingDirectory(const std::string &base);
     248              : 
     249              :   /**
     250              :    * @brief unset working directory
     251              :    *
     252              :    */
     253            2 :   void unsetWorkingDirectory() { working_path_base = ""; }
     254              : 
     255              :   /**
     256              :    * @brief query if the appcontext has working directory set
     257              :    *
     258              :    * @retval true working path base is set
     259              :    * @retval false working path base is not set
     260              :    */
     261              :   bool hasWorkingDirectory() { return !working_path_base.empty(); }
     262              : 
     263              : private:
     264              :   /**
     265              :    * @brief map for Context and Context name
     266              :    *
     267              :    */
     268              :   std::unordered_map<std::string, nntrainer::Context *> engines;
     269              : 
     270              :   std::unordered_map<std::string, std::shared_ptr<nntrainer::MemAllocator>>
     271              :     allocator;
     272              : 
     273              :   std::string working_path_base;
     274              : };
     275              : 
     276              : namespace plugin {}
     277              : 
     278              : } // namespace nntrainer
     279              : 
     280              : #endif /* __ENGINE_H__ */
        

Generated by: LCOV version 2.0-1