Workflow

Implement the compute logic of the operator in the cpukernel/impl/xx.cc files of the operator project.

// Include the header file that declares the operator class.
#include "sample_kernels.h"
// Include the header file of the AI CPU base library.
#include "cust_cpu_utils.h"

namespace {   
// sample is the type of the operator registered in the operator prototype. For details, see Operator Prototype Definition.
const char *SAMPLE = "sample";      
}
// Define the aicpu namespace.
namespace aicpu {   
// Implement the Compute function of the custom operator class.
uint32_t SampleCpuKernel::Compute(CpuKernelContext &ctx)  
{
Tensor *x0 = ctx.Input(0);
// Perform basic verification on the input tensor, for example, check whether the input tensor is empty.
// Obtain the input shape and data based on the obtained input tensor x0.
...
Tensor *x1 = ctx.Input(1);
// Perform basic verification on the input tensor, for example, check whether the input tensor is empty.
// Obtain the input shape and data based on the obtained input tensor x1.
...
Tensor *y0 = ctx.Output(0);
// Obtain the output shape and data based on the obtained output tensor y0.
...

AttrValue *attr = ctx.GetAttr(attr);
// Obtain the attribute information and perform basic verification on the attribute, for example, check whether the attribute is empty.
...

// Organize the compute logic based on the input information, obtain the output result, and set the compute result to the output tensor.
...
// Call the Dump log API as required to print related debugging information.
...
// The shape information of the output tensor needs to be updated for a dynamic-shape operator.
...
return 0;
}
// Register the operator implementation.
REGISTER_CPU_KERNEL(SAMPLE, SampleCpuKernel);  
} // namespace aicpu
  1. Include related header file.

    sample_kernels.h stores declarations in Operator Class Declaration.

    cust_cpu_utils.h contains the Dump log API declaration. For details about the API, see Dump Log APIs.

  2. Define the namespace and declare that the constant pointer points to the operator OpType.

    See the following example:

    namespace {   
    // Replace sample with actual OpType.
    const char *SAMPLE = "sample";      
    }

    sample indicates the type of the operator registered in the operator prototype. For details, see the Operator Prototype Definition. SAMPLE is the declared constant pointer that points to the OpType.

  3. Define an aicpu namespace and define the Compute function of the operator in the aicpu namespace to implement the compute logic of the operator.

    The namespace name is fixed to aicpu. The base class and related definitions are all within the aicpu namespace, as shown in the following.

    namespace aicpu {
    uint32_t SampleCpuKernel::Compute(CpuKernelContext &ctx) {
    ... ...
    }

    SampleCpuKernel is the custom operator class defined in the header file. The formal parameter CpuKernelContext is the context of the CPU kernel, including the input and output tensors and attributes of the operator.

  4. Implement the Compute function.

    Obtain and validate the input and output tensor information, organize the compute logic based on the input information, obtain the compute result, and pass the compute result to the output tensor. For details about how to implement the Compute function, see Compute Function Implementation.

  5. Register the operator kernel:

    REGISTER_CPU_KERNEL(SAMPLE, SampleCpuKernel);

    • SAMPLE indicates the string pointer that points to the operator OpType defined in 2.
    • Replace SampleCpuKernel with the name of the custom operator class.