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

Generated by: LCOV version 2.0-1