From f2af88b4d4bcdffb2dc2a3f30401fd15a23650a3 Mon Sep 17 00:00:00 2001 From: Jasmine-up <1549593765@qq.com> Date: Tue, 11 Jul 2023 10:11:12 +0800 Subject: [PATCH] Jasmine commited forth.first test 20230711 --- .vscode/settings.json | 67 +++++++++++++++++++++++ include/factory/layer_factory.hpp | 46 ++++++++-------- include/layer/layer.hpp | 29 +++++----- include/layer/relu_layer.hpp | 35 ++++++------ include/ops/op.hpp | 33 ++++++------ include/ops/relu_op.hpp | 36 +++++-------- source/factory/layer_factory.cpp | 49 +++++++++-------- source/layer/layer.cpp | 19 +++---- source/layer/relu_layer.cpp | 90 +++++++++++++++---------------- source/ops/op.cpp | 9 ++-- source/ops/relu_op.cpp | 26 ++++----- test/test_relu.cpp | 25 +++++---- 12 files changed, 266 insertions(+), 198 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d94394c --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,67 @@ +{ + "files.associations": { + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "complex": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "map": "cpp", + "set": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "semaphore": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp" + } +} \ No newline at end of file diff --git a/include/factory/layer_factory.hpp b/include/factory/layer_factory.hpp index b92252c..68acddc 100644 --- a/include/factory/layer_factory.hpp +++ b/include/factory/layer_factory.hpp @@ -7,26 +7,30 @@ #include "ops/op.hpp" #include "layer/layer.hpp" -namespace kuiper_infer { -class LayerRegisterer { - public: - typedef std::shared_ptr (*Creator)(const std::shared_ptr &op); - - typedef std::map CreateRegistry; - - static void RegisterCreator(OpType op_type, const Creator &creator); - - static std::shared_ptr CreateLayer(const std::shared_ptr &op); - - static CreateRegistry &Registry(); -}; - -class LayerRegistererWrapper { - public: - LayerRegistererWrapper(OpType op_type, const LayerRegisterer::Creator &creator) { - LayerRegisterer::RegisterCreator(op_type, creator); - } -}; +namespace kuiper_infer +{ + class LayerRegisterer + { + public: + // 这是一个函数指针,输入参数为const std::shared_ptr &op,输出参数为std::shared_ptr + typedef std::shared_ptr (*Creator)(const std::shared_ptr &op); + // 这是注册表类型的别名CreateRegistry + typedef std::map CreateRegistry; + // 注册一下算子,将算子的信息塞到map中 + static void RegisterCreator(OpType op_type, const Creator &creator); + // 创建对应的layer并返回 + static std::shared_ptr CreateLayer(const std::shared_ptr &op); + static CreateRegistry &Registry(); + }; + + class LayerRegistererWrapper // 这个是为了实现算子的注册 + { + public: + LayerRegistererWrapper(OpType op_type, const LayerRegisterer::Creator &creator) + { + LayerRegisterer::RegisterCreator(op_type, creator); + } + }; } -#endif //KUIPER_COURSE_INCLUDE_FACTORY_LAYER_FACTORY_HPP_ +#endif // KUIPER_COURSE_INCLUDE_FACTORY_LAYER_FACTORY_HPP_ diff --git a/include/layer/layer.hpp b/include/layer/layer.hpp index ec6b1ef..a612196 100644 --- a/include/layer/layer.hpp +++ b/include/layer/layer.hpp @@ -6,19 +6,20 @@ #define KUIPER_COURSE_INCLUDE_LAYER_LAYER_HPP_ #include #include "data/tensor.hpp" -namespace kuiper_infer { -class Layer { - public: - explicit Layer(const std::string &layer_name); +namespace kuiper_infer +{ + class Layer + { + public: + explicit Layer(const std::string &layer_name); + // 算子执行接口 + virtual void Forwards(const std::vector>> &inputs, + std::vector>> &outputs); + virtual ~Layer() = default; - virtual void Forwards(const std::vector>> &inputs, - std::vector>> &outputs); - // reluLayer中 inputs 等于 x , outputs 等于 y= x,if x>0 - // 计算得到的结果放在y当中,x是输入,放在inputs中 - - virtual ~Layer() = default; - private: - std::string layer_name_; //relu layer "relu" -}; + private: + // 存储算子类型 + std::string layer_name_; // relu layer "relu" + }; } -#endif //KUIPER_COURSE_INCLUDE_LAYER_LAYER_HPP_ +#endif // KUIPER_COURSE_INCLUDE_LAYER_LAYER_HPP_ diff --git a/include/layer/relu_layer.hpp b/include/layer/relu_layer.hpp index f7c0594..619f9f6 100644 --- a/include/layer/relu_layer.hpp +++ b/include/layer/relu_layer.hpp @@ -7,23 +7,22 @@ #include "layer.hpp" #include "ops/relu_op.hpp" -namespace kuiper_infer { -class ReluLayer : public Layer { - public: - ~ReluLayer() override = default; +namespace kuiper_infer +{ + class ReluLayer : public Layer + { + public: + ~ReluLayer() override = default; + // 此处使用了算子基类的指针指向各种算子 + explicit ReluLayer(const std::shared_ptr &op); + // 执行relu 操作的具体函数Forwards,这个函数必须要重写 + void Forwards(const std::vector>> &inputs, + std::vector>> &outputs) override; + // 根据op创建相应的layer + static std::shared_ptr CreateInstance(const std::shared_ptr &op); - // 通过这里,把relu_op中的thresh告知给relu layer, 因为计算的时候要用到 - explicit ReluLayer(const std::shared_ptr &op); - - // 执行relu 操作的具体函数Forwards - void Forwards(const std::vector>> &inputs, - std::vector>> &outputs) override; - - // 下节的内容,不用管 - static std::shared_ptr CreateInstance(const std::shared_ptr &op); - - private: - std::unique_ptr op_; -}; + private: + std::unique_ptr op_; + }; } -#endif //KUIPER_COURSE_INCLUDE_LAYER_RELU_LAYER_HPP_ +#endif // KUIPER_COURSE_INCLUDE_LAYER_RELU_LAYER_HPP_ diff --git a/include/ops/op.hpp b/include/ops/op.hpp index 12d69fb..b3caf8a 100644 --- a/include/ops/op.hpp +++ b/include/ops/op.hpp @@ -4,21 +4,22 @@ #ifndef KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ #define KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ -namespace kuiper_infer { -enum class OpType { - kOperatorUnknown = -1, - kOperatorRelu = 0, -}; - -class Operator { - public: - OpType op_type_ = OpType::kOperatorUnknown; //不是一个具体节点 制定为unknown - - virtual ~Operator() = default; // - - explicit Operator(OpType op_type); -}; - +namespace kuiper_infer +{ + // 算子类型枚举 + enum class OpType + { + kOperatorUnknown = -1, + kOperatorRelu = 0, + }; + class Operator + { + public: + // 存储算子的类型 + OpType op_type_ = OpType::kOperatorUnknown; // 不是一个具体节点 制定为unknown + virtual ~Operator() = default; // 指定为虚函数是为了让Operator成为一个抽象类 + explicit Operator(OpType op_type); + }; } -#endif //KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ +#endif // KUIPER_COURSE_INCLUDE_OPS_OP_HPP_ diff --git a/include/ops/relu_op.hpp b/include/ops/relu_op.hpp index 4d2f837..c21eb3f 100644 --- a/include/ops/relu_op.hpp +++ b/include/ops/relu_op.hpp @@ -5,27 +5,19 @@ #ifndef KUIPER_COURSE_INCLUDE_OPS_RELU_OP_HPP_ #define KUIPER_COURSE_INCLUDE_OPS_RELU_OP_HPP_ #include "op.hpp" -namespace kuiper_infer { -class ReluOperator : public Operator { - public: - ~ReluOperator() override = default; +namespace kuiper_infer +{ + class ReluOperator : public Operator + { + public: + // override是为了保证重写的函数,与基类有相同的签名 + ~ReluOperator() override = default; + explicit ReluOperator(float thresh); + void set_thresh(float thresh); + float get_thresh() const; - explicit ReluOperator(float thresh); - - void set_thresh(float thresh); - - float get_thresh() const; - - private: - // 需要传递到reluLayer中,怎么传递? - float thresh_ = 0.f; // 用于过滤tensor值当中大于thresh的部分 - // relu存的变量只有thresh - // stride padding kernel_size 这些是到时候convOperator需要的 - // operator起到了属性存储、变量的作用 - // operator所有子类不负责具体运算 - // 具体运算由另外一个类Layer类负责 - // y =x , if x >=0 y = 0 if x < 0 - -}; + private: + float thresh_ = 0.f; // 存储阈值 + }; } -#endif //KUIPER_COURSE_INCLUDE_OPS_RELU_OP_HPP_ +#endif // KUIPER_COURSE_INCLUDE_OPS_RELU_OP_HPP_ diff --git a/source/factory/layer_factory.cpp b/source/factory/layer_factory.cpp index e676aec..ab24040 100644 --- a/source/factory/layer_factory.cpp +++ b/source/factory/layer_factory.cpp @@ -5,30 +5,35 @@ #include "factory/layer_factory.hpp" #include -namespace kuiper_infer { -void LayerRegisterer::RegisterCreator(OpType op_type, const Creator &creator) { - CHECK(creator != nullptr) << "Layer creator is empty"; - CreateRegistry ®istry = Registry(); - CHECK_EQ(registry.count(op_type), 0) << "Layer type: " << int(op_type) << " has already registered!"; - registry.insert({op_type, creator}); -} +namespace kuiper_infer +{ + void LayerRegisterer::RegisterCreator(OpType op_type, const Creator &creator) + { + CHECK(creator != nullptr) << "Layer creator is empty"; + CreateRegistry ®istry = Registry(); + CHECK_EQ(registry.count(op_type), 0) << "Layer type: " << int(op_type) << " has already registered!"; + registry.insert({op_type, creator}); + } -std::shared_ptr LayerRegisterer::CreateLayer(const std::shared_ptr &op) { - CreateRegistry ®istry = Registry(); - const OpType op_type = op->op_type_; + std::shared_ptr LayerRegisterer::CreateLayer(const std::shared_ptr &op) + { + CreateRegistry ®istry = Registry(); + const OpType op_type = op->op_type_; - LOG_IF(FATAL, registry.count(op_type) <= 0) << "Can not find the layer type: " << int(op_type); - const auto &creator = registry.find(op_type)->second; + LOG_IF(FATAL, registry.count(op_type) <= 0) << "Can not find the layer type: " << int(op_type); + const auto &creator = registry.find(op_type)->second; - LOG_IF(FATAL, !creator) << "Layer creator is empty!"; - std::shared_ptr layer = creator(op); - LOG_IF(FATAL, !layer) << "Layer init failed!"; - return layer; -} + LOG_IF(FATAL, !creator) << "Layer creator is empty!"; + std::shared_ptr layer = creator(op); + LOG_IF(FATAL, !layer) << "Layer init failed!"; + return layer; + } -LayerRegisterer::CreateRegistry &LayerRegisterer::Registry() { - static CreateRegistry *kRegistry = new CreateRegistry(); - CHECK(kRegistry != nullptr) << "Global layer register init failed!"; - return *kRegistry; -} + LayerRegisterer::CreateRegistry &LayerRegisterer::Registry() + { + // 实现单例 static创建的CreateRegistry是全局变量,系统运行过程中是全局唯一的 + static CreateRegistry *kRegistry = new CreateRegistry(); + CHECK(kRegistry != nullptr) << "Global layer register init failed!"; + return *kRegistry; + } } diff --git a/source/layer/layer.cpp b/source/layer/layer.cpp index 2b942e7..aedea5f 100644 --- a/source/layer/layer.cpp +++ b/source/layer/layer.cpp @@ -3,13 +3,14 @@ // #include "layer/layer.hpp" #include -namespace kuiper_infer { -Layer::Layer(const std::string &layer_name) : layer_name_(layer_name) { - -} - -void Layer::Forwards(const std::vector>> &inputs, - std::vector>> &outputs) { - LOG(FATAL) << "The layer " << this->layer_name_ << " not implement yet!"; -} +namespace kuiper_infer +{ + Layer::Layer(const std::string &layer_name) : layer_name_(layer_name) + { + } + void Layer::Forwards(const std::vector>> &inputs, + std::vector>> &outputs) + { + LOG(FATAL) << "The layer " << this->layer_name_ << " not implement yet!"; + } } \ No newline at end of file diff --git a/source/layer/relu_layer.cpp b/source/layer/relu_layer.cpp index f81cbaf..7358e8d 100644 --- a/source/layer/relu_layer.cpp +++ b/source/layer/relu_layer.cpp @@ -6,61 +6,55 @@ #include "layer/relu_layer.hpp" #include "factory/layer_factory.hpp" -namespace kuiper_infer { -ReluLayer::ReluLayer(const std::shared_ptr &op) : Layer("Relu") { - CHECK(op->op_type_ == OpType::kOperatorRelu) << "Operator has a wrong type: " << int(op->op_type_); - // dynamic_cast是什么意思? 就是判断一下op指针是不是指向一个relu_op类的指针 - // 这边的op不是ReluOperator类型的指针,就报错 - // 我们这里只接受ReluOperator类型的指针 - // 父类指针必须指向子类ReluOperator类型的指针 - // 为什么不讲构造函数设置为const std::shared_ptr &op? - // 为了接口统一,具体下节会说到 - ReluOperator *relu_op = dynamic_cast(op.get()); - - CHECK(relu_op != nullptr) << "Relu operator is empty"; - // 一个op实例和一个layer 一一对应 这里relu op对一个relu layer - // 对应关系 - this->op_ = std::make_unique(relu_op->get_thresh()); -} - -void ReluLayer::Forwards(const std::vector>> &inputs, - std::vector>> &outputs) { - // relu 操作在哪里,这里! - // 我需要该节点信息的时候 直接这么做 - // 实行了属性存储和运算过程的分离!!!!!!!!!!!!!!!!!!!!!!!! - //x就是inputs y = outputs - CHECK(this->op_ != nullptr); - CHECK(this->op_->op_type_ == OpType::kOperatorRelu); - - const uint32_t batch_size = inputs.size(); //一批x,放在vec当中,理解为batchsize数量的tensor,需要进行relu操作 - for (int i = 0; i < batch_size; ++i) { - - CHECK(!inputs.at(i)->empty()); - const std::shared_ptr> &input_data = inputs.at(i); //取出批次当中的一个张量 - - //对张量中的每一个元素进行运算,进行relu运算 - input_data->data().transform([&](float value) { - // 对张良中的没一个元素进行运算 +namespace kuiper_infer +{ + ReluLayer::ReluLayer(const std::shared_ptr &op) : Layer("Relu") + { + CHECK(op->op_type_ == OpType::kOperatorRelu) << "Operator has a wrong type: " << int(op->op_type_); + // dynamic_cast:用于类继承层次间的指针或引用转换。主要还是用于执行“安全的向下转型(safe downcasting)”, + // 也即是基类对象的指针或引用转换为子类对象的指针或引用。 + ReluOperator *relu_op = dynamic_cast(op.get()); + // 如果dynamic_cast转换失败,relu_op将会为nullptr + CHECK(relu_op != nullptr) << "Relu operator is empty"; + // 一个op实例和一个layer 一一对应 这里relu op对一个relu layer + this->op_ = std::make_unique(relu_op->get_thresh()); // 这里相当于是又创建了一个relu_op对象 + } + void ReluLayer::Forwards(const std::vector>> &inputs, + std::vector>> &outputs) + { + CHECK(this->op_ != nullptr); + CHECK(this->op_->op_type_ == OpType::kOperatorRelu); + // 一批x,放在vec当中,理解为batchsize数量的tensor,需要进行relu操作 + const uint32_t batch_size = inputs.size(); + for (int i = 0; i < batch_size; ++i) + { + CHECK(!inputs.at(i)->empty()); + const std::shared_ptr> &input_data = inputs.at(i); // 取出批次当中的一个张量 + // 对张量中的每一个元素进行运算,进行relu运算 + // 此处使用了lambda表达式 + input_data->data().transform([&](float value) + { + // 对张量中的每一个元素进行运算 // 从operator中得到存储的属性 float thresh = op_->get_thresh(); - //x >= thresh + // x >= thresh return x if (value >= thresh) { - return value; // return x + return value; } else { // x<= thresh return 0.f; return 0.f; - } - }); + } }); - // 把结果y放在outputs中 - outputs.push_back(input_data); + // 把结果y放在outputs中 + outputs.push_back(input_data); + } + } + // 根据operator创建一个对应的layer并返回 + std::shared_ptr ReluLayer::CreateInstance(const std::shared_ptr &op) + { + std::shared_ptr relu_layer = std::make_shared(op); + return relu_layer; } -} - -std::shared_ptr ReluLayer::CreateInstance(const std::shared_ptr &op) { - std::shared_ptr relu_layer = std::make_shared(op); - return relu_layer; -} -LayerRegistererWrapper kReluLayer(OpType::kOperatorRelu, ReluLayer::CreateInstance); + LayerRegistererWrapper kReluLayer(OpType::kOperatorRelu, ReluLayer::CreateInstance); // 注册这个算子,这是饿汉式的单例 } \ No newline at end of file diff --git a/source/ops/op.cpp b/source/ops/op.cpp index be5e5d3..f85430a 100644 --- a/source/ops/op.cpp +++ b/source/ops/op.cpp @@ -2,8 +2,9 @@ // Created by fss on 22-12-21. // #include "ops/op.hpp" -namespace kuiper_infer { -Operator::Operator(OpType op_type) : op_type_(op_type) { - -} +namespace kuiper_infer +{ + Operator::Operator(OpType op_type) : op_type_(op_type) + { + } } \ No newline at end of file diff --git a/source/ops/relu_op.cpp b/source/ops/relu_op.cpp index b7a5447..031a476 100644 --- a/source/ops/relu_op.cpp +++ b/source/ops/relu_op.cpp @@ -2,18 +2,18 @@ // Created by fss on 22-12-20. // #include "ops/relu_op.hpp" -namespace kuiper_infer { - -ReluOperator::ReluOperator(float thresh) : thresh_(thresh), Operator(OpType::kOperatorRelu) { - -} - -void ReluOperator::set_thresh(float thresh) { - this->thresh_ = thresh; -} - -float ReluOperator::get_thresh() const { - return thresh_; -} +namespace kuiper_infer +{ + ReluOperator::ReluOperator(float thresh) : thresh_(thresh), Operator(OpType::kOperatorRelu) + { + } + void ReluOperator::set_thresh(float thresh) + { + this->thresh_ = thresh; + } + float ReluOperator::get_thresh() const + { + return thresh_; + } } \ No newline at end of file diff --git a/test/test_relu.cpp b/test/test_relu.cpp index ec29fc4..4f593f8 100644 --- a/test/test_relu.cpp +++ b/test/test_relu.cpp @@ -7,7 +7,8 @@ #include "layer/relu_layer.hpp" #include "factory/layer_factory.hpp" -TEST(test_layer, forward_relu1) { +TEST(test_layer, forward_relu1) +{ using namespace kuiper_infer; float thresh = 0.f; // 初始化一个relu operator 并设置属性 @@ -15,29 +16,30 @@ TEST(test_layer, forward_relu1) { // 有三个值的一个tensor std::shared_ptr> input = std::make_shared>(1, 1, 3); - input->index(0) = -1.f; //output对应的应该是0 - input->index(1) = -2.f; //output对应的应该是0 - input->index(2) = 3.f; //output对应的应该是3 + input->index(0) = -1.f; // output对应的应该是0 + input->index(1) = -2.f; // output对应的应该是0 + input->index(2) = 3.f; // output对应的应该是3 // 主要第一个算子,经典又简单,我们这里开始! - std::vector>> inputs; //作为一个批次去处理 - - std::vector>> outputs; //放结果 + std::vector>> inputs; // 作为一个批次去处理 + std::vector>> outputs; // 放结果 inputs.push_back(input); ReluLayer layer(relu_op); // 因为是4.1 所以没有作业 4.2才有 -// 一个批次是1 + // 一个批次是1 layer.Forwards(inputs, outputs); ASSERT_EQ(outputs.size(), 1); - for (int i = 0; i < outputs.size(); ++i) { + for (int i = 0; i < outputs.size(); ++i) + { ASSERT_EQ(outputs.at(i)->index(0), 0.f); ASSERT_EQ(outputs.at(i)->index(1), 0.f); ASSERT_EQ(outputs.at(i)->index(2), 3.f); } } -TEST(test_layer, forward_relu2) { +TEST(test_layer, forward_relu2) +{ using namespace kuiper_infer; float thresh = 0.f; std::shared_ptr relu_op = std::make_shared(thresh); @@ -52,7 +54,8 @@ TEST(test_layer, forward_relu2) { inputs.push_back(input); relu_layer->Forwards(inputs, outputs); ASSERT_EQ(outputs.size(), 1); - for (int i = 0; i < outputs.size(); ++i) { + for (int i = 0; i < outputs.size(); ++i) + { ASSERT_EQ(outputs.at(i)->index(0), 0.f); ASSERT_EQ(outputs.at(i)->index(1), 0.f); ASSERT_EQ(outputs.at(i)->index(2), 3.f);