Skip to content

Commit

Permalink
[GPU] Added cl_context and compute engine information
Browse files Browse the repository at this point in the history
Created enum LayerComputeEngine at layer.h API level
Modified layer.h, factory.cpp, layer_node.h/cpp to propagate compute engine information
Added cl_context to handle global configuration of OpenCL environment
Modified RunLayerContext to enable getter/setter for compute engine
Added kernel creation utility in RunLayerContext
Used FullyConnected layer as example for propagating compute info

Signed-off-by: Debadri Samaddar <[email protected]>
  • Loading branch information
s-debadri committed Feb 23, 2024
1 parent a31bed2 commit 295fb51
Show file tree
Hide file tree
Showing 9 changed files with 513 additions and 10 deletions.
19 changes: 15 additions & 4 deletions api/ccapi/include/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* @date 14 October 2020
* @see https://github.com/nnstreamer/nntrainer
* @author Parichay Kapoor <[email protected]>
* @author Debadri Samaddar <[email protected]>
* @bug No known bugs except for NYI items
* @brief This is layers interface for c++ API
*
Expand Down Expand Up @@ -100,6 +101,14 @@ enum LayerType {
LAYER_UNKNOWN = ML_TRAIN_LAYER_TYPE_UNKNOWN /**< Unknown */
};

/**
* @brief Enumeration of layer compute engine
*/
enum LayerComputeEngine {
CPU, /**< CPU as the compute engine */
GPU, /**< GPU as the compute engine */
};

/**
* @class Layer Base class for layers
* @brief Base class for all layers
Expand Down Expand Up @@ -239,7 +248,8 @@ class Layer {
*/
std::unique_ptr<Layer>
createLayer(const LayerType &type,
const std::vector<std::string> &properties = {});
const std::vector<std::string> &properties = {},
const LayerComputeEngine &compute_engine = LayerComputeEngine::CPU);

/**
* @brief Factory creator with constructor for layer
Expand Down Expand Up @@ -279,9 +289,10 @@ Input(const std::vector<std::string> &properties = {}) {
/**
* @brief Helper function to create fully connected layer
*/
inline std::unique_ptr<Layer>
FullyConnected(const std::vector<std::string> &properties = {}) {
return createLayer(LayerType::LAYER_FC, properties);
inline std::unique_ptr<Layer> FullyConnected(
const std::vector<std::string> &properties = {},
const LayerComputeEngine &compute_engine = LayerComputeEngine::CPU) {
return createLayer(LayerType::LAYER_FC, properties, compute_engine);
}

/**
Expand Down
6 changes: 4 additions & 2 deletions api/ccapi/src/factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* @date 14 October 2020
* @see https://github.com/nnstreamer/nntrainer
* @author Parichay Kapoor <[email protected]>
* @author Debadri Samaddar <[email protected]>
* @bug No known bugs except for NYI items
* @brief This is implementaion for factory builder interface for c++ API
*/
Expand All @@ -28,8 +29,9 @@ namespace ml {
namespace train {

std::unique_ptr<Layer> createLayer(const LayerType &type,
const std::vector<std::string> &properties) {
return nntrainer::createLayerNode(type, properties);
const std::vector<std::string> &properties,
const LayerComputeEngine &compute_engine) {
return nntrainer::createLayerNode(type, properties, compute_engine);
}

/**
Expand Down
106 changes: 106 additions & 0 deletions nntrainer/cl_context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// SPDX-License-Identifier: Apache-2.0
/**
* Copyright (C) 2024 Debadri Samaddar <[email protected]>
*
* @file cl_context.h
* @date 23 Feb 2024
* @see https://github.com/nnstreamer/nntrainer
* @author Debadri Samaddar <[email protected]>
* @bug No known bugs except for NYI items
* @brief This file contains app context related functions and classes that
* manages the global configuration of the current OpenCL environment. It also
* creates the OpenCL command queue and context.
*/

#include <cl_context.h>
#include <fc_layer.h>

namespace nntrainer {

std::mutex cl_factory_mutex;

std::once_flag global_cl_context_init_flag;

static void add_default_object(ClContext &cc) {
using LayerType = ml::train::LayerType;

cc.registerFactory(nntrainer::createLayer<FullyConnectedLayer>,
FullyConnectedLayer::type, LayerType::LAYER_FC);
}

static void registerer(ClContext &cc) noexcept {
try {
add_default_object(cc);
} catch (std::exception &e) {
ml_loge("cl_context: registering layers failed!!, reason: %s", e.what());
} catch (...) {
ml_loge("cl_context: registering layer failed due to unknown reason");
}
};

ClContext &ClContext::Global() {
static ClContext instance;

// initializing commandqueue and context
bool result = instance.clInit();

if (!result) {
ml_loge("cl_context: opencl command queue creation failed");
}

/// in g++ there is a bug that hangs up if caller throws,
/// so registerer is noexcept although it'd better not
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70298
std::call_once(global_cl_context_init_flag, registerer, std::ref(instance));
return instance;
}

template <typename T>
const int ClContext::registerFactory(const FactoryType<T> factory,
const std::string &key,
const int int_key) {
static_assert(isSupported<T>::value,
"cl_context: given type is not supported for current context");

auto &index = std::get<IndexType<T>>(factory_map);
auto &str_map = std::get<StrIndexType<T>>(index);
auto &int_map = std::get<IntIndexType>(index);

std::string assigned_key = key == "" ? factory({})->getType() : key;

std::transform(assigned_key.begin(), assigned_key.end(), assigned_key.begin(),
[](unsigned char c) { return std::tolower(c); });

const std::lock_guard<std::mutex> lock(cl_factory_mutex);
if (str_map.find(assigned_key) != str_map.end()) {
std::stringstream ss;
ss << "cl_context: cannot register factory with already taken key: " << key;
throw std::invalid_argument(ss.str().c_str());
}

if (int_key != -1 && int_map.find(int_key) != int_map.end()) {
std::stringstream ss;
ss << "cl_context: cannot register factory with already taken int key: "
<< int_key;
throw std::invalid_argument(ss.str().c_str());
}

int assigned_int_key = int_key == -1 ? str_map.size() + 1 : int_key;

str_map[assigned_key] = factory;
int_map[assigned_int_key] = assigned_key;

ml_logd("cl_context: factory has registered with key: %s, int_key: %d",
assigned_key.c_str(), assigned_int_key);

return assigned_int_key;
}

/**
* @copydoc const int ClContext::registerFactory
*/
template const int ClContext::registerFactory<nntrainer::Layer>(
const FactoryType<nntrainer::Layer> factory, const std::string &key,
const int int_key);

} // namespace nntrainer
Loading

0 comments on commit 295fb51

Please sign in to comment.