Stack Exchange
Tensorflow: how to add user custom op accepting two 1D vec tensor and output a scalar?
I'm trying below but not work.
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/op_kernel.h"
using namespace tensorflow;
REGISTER_OP("Auc")
.Input("predicts: T1")
.Input("labels: T2")
.Output("z: double")
.Attr("T1: {float, double}")
.Attr("T2: {int32, int64}")
.SetIsCommutative()
.Doc(R"doc(
Given preidicts and labels output it's auc
)doc");

class AucOp : public OpKernel {
public:
explicit AucOp(OpKernelConstruction* context) : OpKernel(context) {}

void Compute(OpKernelContext* context) override {
    // Grab the input tensor
    const Tensor& predicts_tensor = context->input(0);
    const Tensor& labels_tensor = context->input(1);
    auto predicts = predicts_tensor.flat<double>();
    auto labels = labels_tensor.flat<int32>();

    // Create an output tensor
    Tensor* output_tensor = NULL;
    TensorShape output_shape;
    OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output_tensor));

    output_tensor->flat<double>().setConstant(predicts(0) * labels(0));
}
};

REGISTER_KERNEL_BUILDER(Name("Auc").Device(DEVICE_CPU), AucOp);


test.py 

predicts = tf.constant([0.8, 0.5, 0.12])
labels = tf.constant([-1, 1, 1])

output = tf.user_ops.auc(predicts, labels)

with tf.Session() as sess:
    init = tf.initialize_all_variables()
    sess.run(init)

    print output.eval()

./test.py 
I tensorflow/core/common_runtime/local_device.cc:40] Local device intra op parallelism threads: 8
I tensorflow/core/common_runtime/direct_session.cc:60] Direct session inter op parallelism threads: 8
F ./tensorflow/core/public/tensor.h:453] Check failed: dtype() ==  DataTypeToEnum::v() (1 vs. 2)
Aborted

I find the problem it's due to type mismatch..

The issue is that the predicts tensor in your Python program has type float, and your op registration accepts this as a valid type for the predicts input (since T1 can be float or double), but AucOp::Compute() assumes that the predicts input always has type double (in the call to predicts_tensor.flat<double>()). The tensorflow::Tensor class does not convert the type of elements in the tensor when you ask for values of a different type, and instead it raises a fatal error.
There are several possible solutions:

To get things working quickly, you could change the type of predicts in your Python program to tf.float64 (which is a synonym for double in the Python front-end):
predicts = tf.constant([0.8, 0.5, 0.12], dtype=tf.float64)

You could start by defining a simpler op that accepts inputs of a single type only:
REGISTER_OP("Auc")
.Input("predicts: double")
.Input("labels: int32")
...;

You could add code in the AucOp::Compute() method to test the input type and access the input values as appropriate. (Use this->input_type(i) to find the type of the ith input.
You could define a templated class AucOp<TPredict, TLabel>, then use TypeConstraint<> in the REGISTER_KERNEL_BUILDER call to define specializations for each of the four valid combinations of prediction and label types. This would look something like:
REGISTER_KERNEL_BUILDER(Name("Auc")
                            .Device(DEVICE_CPU)
                            .TypeConstraint<float>("T1")
                            .TypeConstraint<int32>("T2"),
                       AucOp<float, int32>);
// etc. for AucOp<double, int32>, AucOp<float, int64>, and AucOp<double, int64>.


