在自定义张量流op中使用Eigen

时间:2017-05-04 15:12:11

标签: c++ tensorflow eigen

如何在自定义Tensorflow操作中使用Eigen的内部函数,如Eigen :: internal :: scalar_product_op?在完成Tensorflow代码库之后,例如cwise_ops_common.hcwise_ops.h,我提出了以下(准系统)实现:

#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/framework/shape_inference.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"

#include "tensorflow/core/framework/numeric_types.h"
#include "tensorflow/core/framework/tensor_types.h"
#include "tensorflow/core/platform/types.h"

using namespace tensorflow;

typedef Eigen::ThreadPoolDevice CPUDevice;

REGISTER_OP("CustomMul")
    .Input("to_zero: int8")
    .Output("zeroed: int8")
    .SetShapeFn([](::tensorflow::shape_inference::InferenceContext* c) {
      c->set_output(0, c->input(0));
      return Status::OK();
    });

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

  void Compute(OpKernelContext* context) override {
    // Grab the input tensor
    const Tensor& a_tensor = context->input(0);
    const Tensor& b_tensor = context->input(0);
    auto a = a_tensor.flat<int8>();
    auto b = b_tensor.flat<int8>();

    // Create an output tensor
    Tensor* output_tensor = NULL;
    OP_REQUIRES_OK(context, context->allocate_output(0, b_tensor.shape(),
                                                     &output_tensor));
    auto output = output_tensor->flat<int8>();
    const CPUDevice& d = context->eigen_device<CPUDevice>();
    // Multiply the tensors
    To32Bit(output).device(d) = 
        To32Bit(a).binaryExpr(b, typename Eigen::internal::scalar_product_op<int8>());
  }
};

REGISTER_KERNEL_BUILDER(Name("CustomMul").Device(DEVICE_CPU), CustomMulOp);

使用

编译上述代码
TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())')

g++ -std=c++11 -shared custom_mul.cc -o custom_mul.so -fPIC -I $TF_INC -O2

产生以下错误:

In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:112:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h: In instantiation of ‘bool Eigen::TensorEvaluator<Derived, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<Derived, Device>::CoeffReturnType*) [with Derived = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<Derived, Device>::CoeffReturnType = signed char]’:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorAssign.h:123:5:   required from ‘bool Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar*) [with LeftArgType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; RightArgType = const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar = signed char]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h:35:66:   required from ‘static void Eigen::internal::TensorExecutor<Expression, Device, Vectorizable>::run(const Expression&, const Device&) [with Expression = const Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> > >; Device = Eigen::ThreadPoolDevice; bool Vectorizable = false]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h:35:62:   required from ‘Eigen::TensorDevice<ExpressionType, DeviceType>& Eigen::TensorDevice<ExpressionType, DeviceType>::operator=(const OtherDerived&) [with OtherDerived = Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; ExpressionType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; DeviceType = Eigen::ThreadPoolDevice]’
custom_mul.cc:41:85:   required from here
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:59:16: error: invalid use of incomplete type ‘const struct Eigen::ThreadPoolDevice’
       m_device.memcpy((void*)dest, m_data, sizeof(Scalar) * m_dims.TotalSize());
       ~~~~~~~~~^~~~~~
In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:92:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h:84:8: note: forward declaration of ‘struct Eigen::ThreadPoolDevice’
 struct ThreadPoolDevice;
        ^~~~~~~~~~~~~~~~
In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:112:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h: In instantiation of ‘bool Eigen::TensorEvaluator<const Derived, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Derived, Device>::CoeffReturnType*) [with Derived = Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Derived, Device>::CoeffReturnType = const signed char]’:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:404:5:   required from ‘bool Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::CoeffReturnType*) [with BinaryOp = Eigen::internal::scalar_product_op<signed char, signed char>; LeftArgType = const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>; RightArgType = const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer>; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::CoeffReturnType = signed char]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorAssign.h:128:62:   required from ‘bool Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar*) [with LeftArgType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; RightArgType = const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar = signed char]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h:35:66:   required from ‘static void Eigen::internal::TensorExecutor<Expression, Device, Vectorizable>::run(const Expression&, const Device&) [with Expression = const Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> > >; Device = Eigen::ThreadPoolDevice; bool Vectorizable = false]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h:35:62:   required from ‘Eigen::TensorDevice<ExpressionType, DeviceType>& Eigen::TensorDevice<ExpressionType, DeviceType>::operator=(const OtherDerived&) [with OtherDerived = Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; ExpressionType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; DeviceType = Eigen::ThreadPoolDevice]’
custom_mul.cc:41:85:   required from here
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:186:16: error: invalid use of incomplete type ‘const struct Eigen::ThreadPoolDevice’
       m_device.memcpy((void*)data, m_data, m_dims.TotalSize() * sizeof(Scalar));
       ~~~~~~~~~^~~~~~
In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:92:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h:84:8: note: forward declaration of ‘struct Eigen::ThreadPoolDevice’
 struct ThreadPoolDevice;
        ^~~~~~~~~~~~~~~~
In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:112:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h: In instantiation of ‘bool Eigen::TensorEvaluator<const Derived, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Derived, Device>::CoeffReturnType*) [with Derived = Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer>; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Derived, Device>::CoeffReturnType = const signed char]’:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:405:5:   required from ‘bool Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::CoeffReturnType*) [with BinaryOp = Eigen::internal::scalar_product_op<signed char, signed char>; LeftArgType = const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>; RightArgType = const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer>; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Eigen::TensorCwiseBinaryOp<BinaryOp, LeftArgType, RightArgType>, Device>::CoeffReturnType = signed char]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorAssign.h:128:62:   required from ‘bool Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::evalSubExprsIfNeeded(Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar*) [with LeftArgType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; RightArgType = const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; Device = Eigen::ThreadPoolDevice; Eigen::TensorEvaluator<const Eigen::TensorAssignOp<LhsXprType, RhsXprType>, Device>::Scalar = signed char]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorExecutor.h:35:66:   required from ‘static void Eigen::internal::TensorExecutor<Expression, Device, Vectorizable>::run(const Expression&, const Device&) [with Expression = const Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> > >; Device = Eigen::ThreadPoolDevice; bool Vectorizable = false]’
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorDevice.h:35:62:   required from ‘Eigen::TensorDevice<ExpressionType, DeviceType>& Eigen::TensorDevice<ExpressionType, DeviceType>::operator=(const OtherDerived&) [with OtherDerived = Eigen::TensorCwiseBinaryOp<Eigen::internal::scalar_product_op<signed char, signed char>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, int>, 16, Eigen::MakePointer>, const Eigen::TensorMap<Eigen::Tensor<const signed char, 1, 1, long int>, 16, Eigen::MakePointer> >; ExpressionType = Eigen::TensorMap<Eigen::Tensor<signed char, 1, 1, int>, 16, Eigen::MakePointer>; DeviceType = Eigen::ThreadPoolDevice]’
custom_mul.cc:41:85:   required from here
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:186:16: error: invalid use of incomplete type ‘const struct Eigen::ThreadPoolDevice’
       m_device.memcpy((void*)data, m_data, m_dims.TotalSize() * sizeof(Scalar));
       ~~~~~~~~~^~~~~~
In file included from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/Tensor:92:0,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/third_party/eigen3/unsupported/Eigen/CXX11/Tensor:4,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/partial_tensor_shape.h:21,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/attr_value_util.h:22,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/node_def_util.h:23,
                 from /home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/tensorflow/core/framework/shape_inference.h:21,
                 from custom_mul.cc:2:
/home/user123/miniconda3/envs/ml/lib/python2.7/site-packages/tensorflow/include/unsupported/Eigen/CXX11/src/Tensor/TensorForwardDeclarations.h:84:8: note: forward declaration of ‘struct Eigen::ThreadPoolDevice’
 struct ThreadPoolDevice;

我正在使用TensorFlow v.1.0.1和GCC 6.3.1。

2 个答案:

答案 0 :(得分:0)

struct ThreadPoolDevice最初只是前向声明(在custom_mul.cc:2),但必须完全定义。这意味着你错过了一些包含。移动此包括

#include <third_party/eigen3/unsupported/Eigen/CXX11/Tensor>

直到代码的开头。我认为应该完全定义ThreadPoolDevice

答案 1 :(得分:0)

您需要先添加#define EIGEN_USE_THREADS,然后再添加third_party/eigen3/unsupported/Eigen/CXX11/Tensor,否则ThreadPoolDevice将不可用。