operator_test.cc 8.7 KB
Newer Older
Q
Qiao Longfei 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/framework/operator.h"
#include "gtest/gtest.h"
Q
Qiao Longfei 已提交
17
#include "paddle/framework/op_info.h"
Q
Qiao Longfei 已提交
18 19 20 21 22
#include "paddle/framework/op_registry.h"

namespace paddle {
namespace framework {

Q
Qiao Longfei 已提交
23 24 25
static int op_run_num = 0;

class OpWithoutKernelTest : public OperatorBase {
Q
Qiao Longfei 已提交
26
 public:
Y
Yu Yang 已提交
27 28
  OpWithoutKernelTest(const std::string& type, const VariableNameMap& inputs,
                      const VariableNameMap& outputs, const AttributeMap& attrs)
Y
Yu Yang 已提交
29
      : OperatorBase(type, inputs, outputs, attrs), x(1) {}
Y
Yu Yang 已提交
30 31
  void InferShape(const Scope& scope) const override {}
  void Run(const Scope& scope,
Y
Yu Yang 已提交
32
           const platform::DeviceContext& dev_ctx) const override {
Y
Yu Yang 已提交
33 34 35 36
    ++op_run_num;
    ASSERT_EQ(static_cast<int>(inputs_.size()), 1);
    ASSERT_EQ(static_cast<int>(outputs_.size()), 1);
    ASSERT_EQ(scope.FindVar(inputs_.at("input")[0]), nullptr);
Q
Qiao Longfei 已提交
37
    ASSERT_EQ(x, 1);
Y
Yu Yang 已提交
38
    ASSERT_NE(scope.FindVar(outputs_.at("output")[0]), nullptr);
Q
Qiao Longfei 已提交
39
  }
Q
Qiao Longfei 已提交
40 41

 public:
Y
Yu Yang 已提交
42
  int x{0};
Q
Qiao Longfei 已提交
43 44
};

Q
Qiao Longfei 已提交
45
class OpeWithoutKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
Q
Qiao Longfei 已提交
46
 public:
Q
Qiao Longfei 已提交
47 48
  OpeWithoutKernelTestProtoAndCheckerMaker(OpProto* proto,
                                           OpAttrChecker* op_checker)
Q
Qiao Longfei 已提交
49 50 51
      : OpProtoAndCheckerMaker(proto, op_checker) {
    AddInput("input", "input of test op");
    AddOutput("output", "output of test op");
Q
Qiao Longfei 已提交
52
    AddAttr<float>("scale", "scale of cosine op");
Q
Qiao Longfei 已提交
53 54 55 56 57 58 59
    AddComment("This is test op");
  }
};

}  // namespace framework
}  // namespace paddle

Y
Yu Yang 已提交
60 61 62
static void BuildVar(const std::string& param_name,
                     std::initializer_list<const char*> arguments,
                     paddle::framework::OpDesc::Var* var) {
Y
Yu Yang 已提交
63 64 65 66 67 68
  var->set_parameter(param_name);
  for (auto& arg_name : arguments) {
    *var->mutable_arguments()->Add() = arg_name;
  }
}

F
fengjiayi 已提交
69 70 71
REGISTER_OP_WITHOUT_GRADIENT(
    test_operator, paddle::framework::OpWithoutKernelTest,
    paddle::framework::OpeWithoutKernelTestProtoAndCheckerMaker);
Q
Qiao Longfei 已提交
72 73 74 75

TEST(OperatorBase, all) {
  paddle::framework::OpDesc op_desc;
  op_desc.set_type("test_operator");
Y
Yu Yang 已提交
76 77
  BuildVar("input", {"IN1"}, op_desc.add_inputs());
  BuildVar("output", {"OUT1"}, op_desc.add_outputs());
Y
Yu Yang 已提交
78

Q
Qiao Longfei 已提交
79 80 81
  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
Q
Qiao Longfei 已提交
82
  attr->set_f(3.14);
Q
Qiao Longfei 已提交
83 84

  paddle::platform::CPUDeviceContext device_context;
Y
Yu Yang 已提交
85
  paddle::framework::Scope scope;
Q
Qiao Longfei 已提交
86

Y
Yu Yang 已提交
87
  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
Y
Yu Yang 已提交
88
  scope.NewVar("OUT1");
Q
Qiao Longfei 已提交
89
  ASSERT_EQ(paddle::framework::op_run_num, 0);
90
  op->InferShape(scope);
Q
Qiao Longfei 已提交
91
  op->Run(scope, device_context);
Q
Qiao Longfei 已提交
92
  ASSERT_EQ(paddle::framework::op_run_num, 1);
Q
Qiao Longfei 已提交
93 94 95 96 97
}

namespace paddle {
namespace framework {

Q
Qiao Longfei 已提交
98 99 100 101
class OpKernelTestProtoAndCheckerMaker : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestProtoAndCheckerMaker(OpProto* proto, OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
Y
Yan Chunwei 已提交
102 103 104 105
    AddInput("x", "input of test op");
    AddOutput("y", "output of test op");
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
F
fengjiayi 已提交
106
        .GreaterThan(0.0);
Q
Qiao Longfei 已提交
107 108 109 110
    AddComment("This is test op");
  }
};

Q
Qiao Longfei 已提交
111 112
static int cpu_kernel_run_num = 0;

Q
Qiao Longfei 已提交
113
class OpWithKernelTest : public OperatorWithKernel {
Y
Yu Yang 已提交
114 115 116
 public:
  using OperatorWithKernel::OperatorWithKernel;

Y
Yu Yang 已提交
117
 protected:
Q
Qiao Longfei 已提交
118
  void InferShape(framework::InferShapeContextBase* ctx) const override {}
Y
Yu Yang 已提交
119 120 121
  DataType IndicateDataType(const ExecutionContext& ctx) const override {
    return DataType::FP32;
  }
Q
Qiao Longfei 已提交
122 123
};

124
template <typename T1, typename T2>
Y
Yu Yang 已提交
125
class CPUKernelTest : public OpKernel<float> {
Q
Qiao Longfei 已提交
126
 public:
127
  void Compute(const ExecutionContext& ctx) const {
Y
Yan Chunwei 已提交
128
    std::cout << "this is cpu kernel" << std::endl;
Q
qiaolongfei 已提交
129
    std::cout << ctx.op().DebugString() << std::endl;
Q
Qiao Longfei 已提交
130
    cpu_kernel_run_num++;
Q
qiaolongfei 已提交
131 132
    ASSERT_EQ(ctx.op().Input("x"), "IN1");
    ASSERT_EQ(ctx.op().Output("y"), "OUT1");
Y
Yan Chunwei 已提交
133 134 135 136 137 138 139 140 141
  }
};

class OpKernelTestMultiInputsProtoAndCheckerMaker
    : public OpProtoAndCheckerMaker {
 public:
  OpKernelTestMultiInputsProtoAndCheckerMaker(OpProto* proto,
                                              OpAttrChecker* op_checker)
      : OpProtoAndCheckerMaker(proto, op_checker) {
Y
Yu Yang 已提交
142
    AddInput("xs", "inputs of test op").AsDuplicable();
Y
Yan Chunwei 已提交
143
    AddInput("k", "input of test op");
Y
Yu Yang 已提交
144
    AddOutput("ys", "outputs of test op").AsDuplicable();
Y
Yan Chunwei 已提交
145 146
    AddAttr<float>("scale", "scale of cosine op")
        .SetDefault(1.0)
F
fengjiayi 已提交
147
        .GreaterThan(0.0);
Y
Yan Chunwei 已提交
148 149 150 151
    AddComment("This is test op");
  }
};

Y
Yu Yang 已提交
152
class CPUKernalMultiInputsTest : public OpKernel<float> {
Y
Yan Chunwei 已提交
153
 public:
154
  void Compute(const ExecutionContext& ctx) const {
Q
qiaolongfei 已提交
155
    auto xs = ctx.op().Inputs("xs");
Y
Yan Chunwei 已提交
156 157 158 159 160
    ASSERT_EQ(xs.size(), 3UL);
    ASSERT_EQ(xs[0], "x0");
    ASSERT_EQ(xs[1], "x1");
    ASSERT_EQ(xs[2], "x2");

161
    auto inVar0 = ctx.MultiInputVar("xs");
162
    ASSERT_EQ(inVar0.size(), 3U);
163 164 165 166 167

    auto intVar1 = ctx.InputVar("k");
    ASSERT_NE(intVar1, nullptr);

    auto outVar0 = ctx.MultiOutputVar("ys");
168
    ASSERT_EQ(outVar0.size(), 2U);
169 170

    auto inTensor0 = ctx.MultiInput<Tensor>("xs");
171
    ASSERT_EQ(inTensor0.size(), 3U);
172 173 174 175 176

    auto intTensor1 = ctx.Input<Tensor>("k");
    ASSERT_NE(intTensor1, nullptr);

    auto outTensor0 = ctx.MultiOutput<Tensor>("ys");
177
    ASSERT_EQ(outTensor0.size(), 2U);
178

Q
qiaolongfei 已提交
179
    auto k = ctx.op().Input("k");
Y
Yan Chunwei 已提交
180 181
    ASSERT_EQ(k, "k0");

Q
qiaolongfei 已提交
182
    auto ys = ctx.op().Outputs("ys");
Y
Yan Chunwei 已提交
183 184 185
    ASSERT_EQ(ys.size(), 2UL);
    ASSERT_EQ(ys[0], "y0");
    ASSERT_EQ(ys[1], "y1");
Q
Qiao Longfei 已提交
186 187 188
  }
};

Y
Yu Yang 已提交
189 190 191
}  // namespace framework
}  // namespace paddle

F
fengjiayi 已提交
192 193 194
REGISTER_OP_WITHOUT_GRADIENT(
    op_with_kernel, paddle::framework::OpWithKernelTest,
    paddle::framework::OpKernelTestProtoAndCheckerMaker);
195 196
REGISTER_OP_CPU_KERNEL(op_with_kernel,
                       paddle::framework::CPUKernelTest<float, float>);
Q
Qiao Longfei 已提交
197

Y
Yan Chunwei 已提交
198
// test with single input
Q
Qiao Longfei 已提交
199
TEST(OpKernel, all) {
Q
Qiao Longfei 已提交
200
  paddle::framework::OpDesc op_desc;
Q
Qiao Longfei 已提交
201
  op_desc.set_type("op_with_kernel");
Y
Fix CI  
Yu Yang 已提交
202 203
  BuildVar("x", {"IN1"}, op_desc.add_inputs());
  BuildVar("y", {"OUT1"}, op_desc.add_outputs());
Y
Yu Yang 已提交
204

Q
Qiao Longfei 已提交
205 206 207 208 209
  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

Y
Yu Yang 已提交
210
  paddle::platform::CPUDeviceContext cpu_device_context;
Y
Yu Yang 已提交
211
  paddle::framework::Scope scope;
Q
Qiao Longfei 已提交
212

Y
Yu Yang 已提交
213
  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
Q
Qiao Longfei 已提交
214
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 0);
Q
Qiao Longfei 已提交
215
  op->Run(scope, cpu_device_context);
Q
Qiao Longfei 已提交
216
  ASSERT_EQ(paddle::framework::cpu_kernel_run_num, 1);
Q
Qiao Longfei 已提交
217
}
Y
Yan Chunwei 已提交
218

F
fengjiayi 已提交
219 220 221
REGISTER_OP_WITHOUT_GRADIENT(
    op_multi_inputs_with_kernel, paddle::framework::OpWithKernelTest,
    paddle::framework::OpKernelTestMultiInputsProtoAndCheckerMaker);
Y
Yan Chunwei 已提交
222 223 224 225 226 227 228 229 230
REGISTER_OP_CPU_KERNEL(op_multi_inputs_with_kernel,
                       paddle::framework::CPUKernalMultiInputsTest);

// test with multi inputs
TEST(OpKernel, multi_inputs) {
  using namespace paddle::framework;

  OpDesc op_desc;
  op_desc.set_type("op_multi_inputs_with_kernel");
Y
Yu Yang 已提交
231 232 233
  BuildVar("xs", {"x0", "x1", "x2"}, op_desc.add_inputs());
  BuildVar("k", {"k0"}, op_desc.add_inputs());
  BuildVar("ys", {"y0", "y1"}, op_desc.add_outputs());
Y
Yu Yang 已提交
234

Y
Yan Chunwei 已提交
235 236 237 238 239 240
  auto attr = op_desc.mutable_attrs()->Add();
  attr->set_name("scale");
  attr->set_type(paddle::framework::AttrType::FLOAT);
  attr->set_f(3.14);

  paddle::platform::CPUDeviceContext cpu_device_context;
Y
Yu Yang 已提交
241
  paddle::framework::Scope scope;
242 243 244 245 246 247
  scope.NewVar("x0")->GetMutable<Tensor>();
  scope.NewVar("x1")->GetMutable<Tensor>();
  scope.NewVar("x2")->GetMutable<Tensor>();
  scope.NewVar("k0")->GetMutable<Tensor>();
  scope.NewVar("y0")->GetMutable<Tensor>();
  scope.NewVar("y1")->GetMutable<Tensor>();
Y
Yan Chunwei 已提交
248

Y
Yu Yang 已提交
249
  auto op = paddle::framework::OpRegistry::CreateOp(op_desc);
Y
Yan Chunwei 已提交
250 251
  op->Run(scope, cpu_device_context);
}
Y
Yu Yang 已提交
252 253 254 255

class OperatorClone : public paddle::framework::OperatorBase {
 public:
  DEFINE_OP_CLONE_METHOD(OperatorClone);
Y
Yu Yang 已提交
256 257 258
  OperatorClone(const std::string& type,
                const paddle::framework::VariableNameMap& inputs,
                const paddle::framework::VariableNameMap& outputs,
Y
Yu Yang 已提交
259 260 261 262 263 264 265 266 267
                const paddle::framework::AttributeMap& attrs)
      : OperatorBase(type, inputs, outputs, attrs) {}
  void InferShape(const paddle::framework::Scope& scope) const override {}
  void Run(const paddle::framework::Scope& scope,
           const paddle::platform::DeviceContext& dev_ctx) const override {}
};

TEST(Operator, Clone) {
  OperatorClone a("ABC", {}, {}, {});
Y
Yu Yang 已提交
268
  auto b = a.Clone();
Y
Yu Yang 已提交
269
  ASSERT_EQ(a.Type(), b->Type());
270
}