Updated on 2022-03-13 GMT+08:00

Parsing an Operator

For a newly developed custom operator, you need to customize a function for parsing operator attributes and converting the operator attribute definitions in the source model to the operator attribute definitions in the offline model supported by the Ascend AI processor. If you are rewriting a built-in operator of the Ascend AI processor, skip this step. A built-in operator is automatically parsed by its plug-in.

Function Declaration

The operator parsing function is declared as follows:

Status ParseParamsxx(const Message* op_origin, ge::Operator& op_dest)
  • ParseParamsxx: function name, which is user-defined and must be unique
  • op_origin: source operator model. It is a data struct in the protobuf format. It is derived from the .proto file of the Caffe model in the /include/inc/custom/proto/caffe/caffe.proto directory under the DDK installation directory. If the custom operator is not defined in the caffe.proto file, add the operator definition by referring to caffe.proto File Operator Definition (Optional).

    The operator plug-in reads operator attributes based on the operator name from the proto/caffe/caffe.pb.h file and caffe.pb.cc file generated after caffe.proto building and parses the operator attributes to convert the operator data structure to a data structure supported by the offline model.

    Find the preset caffe.proto file in /include/inc/custom/proto/caffe/caffe.proto in the DDK installation path. You can modify the file and add the definition of the custom operator.

  • op_dest: target operator model. As the operator data struct of the offline model supported by the Ascend AI processor, it stores operator information. For details about class Operator, see Class Operator in GE API Reference.

Procedure

Implement the ParseParamsxx function as follows:

  1. Define the object that points to LayerParameter and obtain the handle to the current operator layer.

    const caffe::LayerParameter* layer =dynamic_cast<const caffe::LayerParameter*>(op_origin);
    const caffe::xxxParameter& param = layer->reduction_param();

    In the preceding information:

    • xxxParameter in caffe::xxxParameter of the param object must be the same as the type declared in the LayerParameter object.
    • The name of the member function xxx_param() of the layer object must be the same as the object name declared in the LayerParameter object.

    The following uses the Reduction and convolution operators in caffe.proto as an example:

    message LayerParameter {
    optional ReductionParameter reduction_param = 136;
    optional ConvolutionParameter convolution_param = 106;
    ...
    }

    The code for obtaining the handles to the Reduction and Convolution operator layers are as follows:

    const caffe::ReductionParameter& param = layer->reduction_param()

    const caffe::ConvolutionParameter& param = layer->convolution_param()

  2. Parse the operator attributes and assign the attributes to the op_dest object of the Operator type.

    You can call the CreateFrom<AttrValue::T>(DT&& val) API to convert DT parameters to T parameters of class AttrValue and call the SetAttr(const string& name, const AttrValue& value) API to assign the converted values of the AttrValue object to the corresponding attributes of the op_dest object.

    Type T is introduced to the Ascend AI software stack to simplify the type definition. The supported data types are renamed. For the mapping between type T and the source data type, see Table 1. For the prototype definitions, see the include/inc/graph/attr_value.h file in the DDK installation directory.

    Table 1 Mapping between type T and source data types

    T Type

    Source Data Type

    INT

    int64_t

    FLOAT

    float

    STR

    std::string

    TENSOR

    TensorPtr

    TENSOR_DESC

    TensorDesc

    GRAPH

    ComputeGraphPtr

    BYTES

    Buffer

    NAMED_ATTRS

    NamedAttrs

    BOOL

    bool

    LIST_INT

    vector<INT>

    LIST_FLOAT

    vector<FLOAT>

    LIST_BOOL

    vector<BOOL>

    LIST_STR

    vector<STR>

    LIST_TENSOR

    vector<TENSOR>

    LIST_TENSOR_DESC

    vector<TENSOR_DESC>

    LIST_GRAPH

    vector<GRAPH>

    LIST_BYTES

    vector<BYTES>

    LIST_NAMED_ATTRS

    vector<NAMED_ATTRS>

    For details about the SetAttr API, see the GE API Reference.

    The following are examples of parsing common parameters:
    • Parameters of the int or float type

      For example, the operator parameters in the caffe.proto file are defined as follows:

      message ReductionParameter {
        ......
        optional int32 axis = 2 [default = 0];                                
        optional float coeff = 3 [default = 1.0]; 
      }

      Call the SetAttr API to assign the value of param.axis() to the axis attribute of the op_dest object and convert the type to INT. Assign the value of param.coeff() to the coeff attribute of the op_dest object and convert the type to FLOAT, as follows:

      op_dest.SetAttr("axis", AttrValue::CreateFrom<AttrValue::INT>(param.axis()));    
      op_dest.SetAttr("coeff", AttrValue::CreateFrom<AttrValue::FLOAT>(param.coeff()));  

      In the preceding information, CreateFrom<AttrValue::T>(DT&& val) is used to convert DT parameters to T parameters of the AttrValue class.

    • Parameters of the enum type

      For example, the operator parameters in the caffe.proto file are defined as follows:

      message ReductionParameter {
        enum ReductionOp {
          SUM = 1;
          ASUM = 2;
          SUMSQ = 3;
          MEAN = 4;
        }
      ...}
      1. Convert parameters of the enum type to parameters of the map type.
        std::map<caffe::ReductionParameter_ReductionOp, std::string> operation_map = {
                { caffe::ReductionParameter_ReductionOp_SUM, "SUM" },
            { caffe::ReductionParameter_ReductionOp_ASUM, "ASUM" },
            { caffe::ReductionParameter_ReductionOp_SUMSQ, "SUMSQ" },
            { caffe::ReductionParameter_ReductionOp_MEAN, "MEAN" },
            };
      2. Call the SetAttr API to assign the operation_map parameter of the map type to the operation attribute of the op_dest object.
        op_dest.SetAttr("operation", AttrValue::CreateFrom<AttrValue::STR>(operation_map[param.operation()]));

        For details about the SetAttr API, see the GE API Reference.

    • Parameters of the repeated type

      For example, the operator parameters in the caffe.proto file are defined as follows:

      message xxxParameter {
      ...
        repeated float min_size = 1;
        repeated uint32 offset = 2;
      ....
      }
      1. Convert parameters of the repeated float type to parameters of the vector<float> type, convert parameters of the repeated uint32 type to parameters of the vector<uint32> type, and assign values to the parameters of the vector type.
        vector<float> min_size;      
        vector<uint32> offset;
        for(int i = 0; i < param.min_size_size(); ++i)
        {
           min_size.push_back(param.min_size(i));  // Call the push_back function of the vector type to assign a value to the min_size parameter of the repeated object.
        }
        for(int i = 0; i < param.offset_size(); ++i)
        {
           offset.push_back(param.offset(i)); // Call the push_back function in the vector object to assign a value to the offset parameter of the repeated object.
        }
      2. Call the SetAttr API to assign the value of the min_size parameter of the vector<float> type to the min_size attribute of the op_dest object. Assign the value of the offset parameter of the vector<uint32> type to the offset attribute of the LIST_INT type in the op_dest object.
        op_dest.SetAttr("min_size", ge::AttrValue::CreateFrom<ge::AttrValue::LIST_FLOAT>(min_size)); 
        op_dest.SetAttr("offset", ge::AttrValue::CreateFrom<ge::AttrValue::LIST_INT>(offset));

        For details about the SetAttr API, see the GE API Reference.