kuiperInfer学习笔记

kuiperInfer使用的模型格式是PNNX(PyTorch Neural Network Exchange)

PNNX由图结构(Graph)、运算符(Operator)和操作数(Operand)这三种结构组成。

1. Graph 图结构

 Graph是管理计算图中的运算符(Operator)和操作数(Operand)。

class Graph
{
    Operator* new_operator(const std::string& type, const std::string& name);
    Operator* new_operator_before(const std::string& type, const std::string& name, const Operator* cur);

    Operand* new_operand(const torch::jit::Value* v);
    Operand* new_operand(const std::string& name);
    Operand* get_operand(const std::string& name);

    std::vector<Operator*> ops;
    std::vector<Operand*> operands;
};

2. Operator 运算符结构

class Operator
{
public:
    std::vector<Operand*> inputs;
    std::vector<Operand*> outputs;

    std::string type;
    std::string name;

    std::vector<std::string> inputnames;
    std::map<std::string, Parameter> params;
    std::map<std::string, Attribute> attrs;
};

3. Operand 操作数结构

class Operand
{
public:
    void remove_consumer(const Operator* c);
    Operator* producer;
    std::vector<Operator*> consumers;
    
    int type;
    std::vector<int> shape;

    std::string name;
    std::map<std::string, Parameter> params;
};

4. RuntimeGraph 结构体

private:
  std::string input_name_;  /// 计算图输入节点的名称
  std::string output_name_; /// 计算图输出节点的名称
  std::string param_path_;  /// 计算图的结构文件
  std::string bin_path_;    /// 计算图的权重文件

  std::vector<std::shared_ptr<RuntimeOperator>> operators_;
  std::map<std::string, std::shared_ptr<RuntimeOperator>> operators_maps_;

  std::unique_ptr<pnnx::Graph> graph_; /// pnnx的graph

5. RuntimeOperator 结构体

struct RuntimeOperator {
  virtual ~RuntimeOperator();

  bool has_forward = false;
  std::string name;      /// 计算节点的名称 Operator name 
  std::string type;      /// 计算节点的类型 Operator type
  std::shared_ptr<Layer> layer;  /// 节点对应的计算Layer

  std::vector<std::string> output_names;  /// 节点的输出节点名称
  std::shared_ptr<RuntimeOperand> output_operands;  /// 节点的输出操作数

  std::map<std::string, std::shared_ptr<RuntimeOperand>> input_operands;  /// 节点的输入操作数
  std::vector<std::shared_ptr<RuntimeOperand>> input_operands_seq;  /// 节点的输入操作数,顺序排列
  std::map<std::string, std::shared_ptr<RuntimeOperator>> output_operators;  /// 输出节点的名字和节点对应

  std::map<std::string, RuntimeParameter*> params;  /// 算子的参数信息
  std::map<std::string, std::shared_ptr<RuntimeAttribute>>
      attribute;  /// 算子的属性信息,内含权重信息
};

6. RuntimeOperand 结构体

struct RuntimeOperand {
  std::string name;                                     /// 操作数的名称
  std::vector<int32_t> shapes;                          /// 操作数的形状
  std::vector<std::shared_ptr<Tensor<float>>> datas;    /// 存储操作数
  RuntimeDataType type = RuntimeDataType::kTypeUnknown; /// 操作数的类型,一般是float
};

7. RuntimeAttribute 结构体

/// 计算图节点的属性信息
struct RuntimeAttribute {
  std::vector<char> weight_data;  /// 节点中的权重参数
  std::vector<int> shape;         /// 节点中的形状信息
  RuntimeDataType type = RuntimeDataType::kTypeUnknown;  /// 节点中的数据类型

  /**
   * 从节点中加载权重参数
   * @tparam T 权重类型
   * @return 权重参数数组
   */
  template <class T>  //
  std::vector<T> get(bool need_clear_weight = true);

  /**
   * 清除权重
   */
  void ClearWeight();
};

class Attribute
{
public:
    Attribute()
        : type(0)
    {
    }

#if BUILD_PNNX
    Attribute(const at::Tensor& t);
#endif // BUILD_PNNX

    Attribute(const std::initializer_list<int>& shape, const std::vector<float>& t);

    // 0=null 1=f32 2=f64 3=f16 4=i32 5=i64 6=i16 7=i8 8=u8 9=bool
    int type;
    std::vector<int> shape;

    std::vector<char> data;
};

    bool RuntimeGraph::Init() {
        if (this->bin_path_.empty() || this->param_path_.empty()) {
            LOG(ERROR) << "The bin path or param path is empty";
            return false;
        }

        this->graph_ = std::make_unique<pnnx::Graph>();
        int load_result = this->graph_->load(param_path_, bin_path_);
        if (load_result != 0) {
            LOG(ERROR) << "Can not find the param path or bin path: " << param_path_
                       << " " << bin_path_;
            return false;
        }

        std::vector<pnnx::Operator *> operators = this->graph_->ops;
        if (operators.empty()) {
            LOG(ERROR) << "Can not read the layers' define";
            return false;
        }

        this->operators_.clear();
        this->operators_maps_.clear();
        for (const pnnx::Operator *op: operators) {
            if (!op) {
                LOG(ERROR) << "Meet the empty node";
                continue;
            } else {
                std::shared_ptr<RuntimeOperator> runtime_operator =
                        std::make_shared<RuntimeOperator>();
                // 初始化算子的名称
                /* Operator{name, type} => RuntimeOperator{name, type} */
                runtime_operator->name = op->name;
                runtime_operator->type = op->type;

                // 初始化算子中的input
                /* 输出: RuntimeOperator{input_operands, input_operands_seq} */
                /* 输入:  Operator{inputs} */
                /* producer{name};  type; shape*/
                const std::vector<pnnx::Operand *> &inputs = op->inputs;
                if (!inputs.empty()) {
                    InitGraphOperatorsInput(inputs, runtime_operator);
                }

                // 记录输出operand中的名称
                /* 输出: RuntimeOperator{output_names} */
                /* 输入:  Operator{outputs} */
                /* consumers{name} */
                const std::vector<pnnx::Operand *> &outputs = op->outputs;
                if (!outputs.empty()) {
                    InitGraphOperatorsOutput(outputs, runtime_operator);
                }

                // 初始化算子中的attribute(权重)
                const std::map<std::string, pnnx::Attribute> &attrs = op->attrs;
                if (!attrs.empty()) {
                    InitGraphAttrs(attrs, runtime_operator);
                }

                // 初始化算子中的parameter
                const std::map<std::string, pnnx::Parameter> &params = op->params;
                if (!params.empty()) {
                    InitGraphParams(params, runtime_operator);
                }
                this->operators_.push_back(runtime_operator);
                this->operators_maps_.insert({runtime_operator->name, runtime_operator});
            }
        }

        return true;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值