operator_test.cc 8.5 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 {}
Q
Qiao Longfei 已提交
119 120
};

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

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

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

158
    auto inVar0 = ctx.MultiInputVar("xs");
159
    ASSERT_EQ(inVar0.size(), 3U);
160 161 162 163 164

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

    auto outVar0 = ctx.MultiOutputVar("ys");
165
    ASSERT_EQ(outVar0.size(), 2U);
166 167

    auto inTensor0 = ctx.MultiInput<Tensor>("xs");
168
    ASSERT_EQ(inTensor0.size(), 3U);
169 170 171 172 173

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

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

Q
qiaolongfei 已提交
176
    auto k = ctx.op().Input("k");
Y
Yan Chunwei 已提交
177 178
    ASSERT_EQ(k, "k0");

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

Y
Yu Yang 已提交
186 187 188
}  // namespace framework
}  // namespace paddle

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

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

Q
Qiao Longfei 已提交
202 203 204 205 206
  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 已提交
207
  paddle::platform::CPUDeviceContext cpu_device_context;
Y
Yu Yang 已提交
208
  paddle::framework::Scope scope;
Q
Qiao Longfei 已提交
209

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

F
fengjiayi 已提交
216 217 218
REGISTER_OP_WITHOUT_GRADIENT(
    op_multi_inputs_with_kernel, paddle::framework::OpWithKernelTest,
    paddle::framework::OpKernelTestMultiInputsProtoAndCheckerMaker);
Y
Yan Chunwei 已提交
219 220 221 222 223 224 225 226 227
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 已提交
228 229 230
  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 已提交
231

Y
Yan Chunwei 已提交
232 233 234 235 236 237
  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 已提交
238
  paddle::framework::Scope scope;
239 240 241 242 243 244
  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 已提交
245

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

class OperatorClone : public paddle::framework::OperatorBase {
 public:
  DEFINE_OP_CLONE_METHOD(OperatorClone);
Y
Yu Yang 已提交
253 254 255
  OperatorClone(const std::string& type,
                const paddle::framework::VariableNameMap& inputs,
                const paddle::framework::VariableNameMap& outputs,
Y
Yu Yang 已提交
256 257 258 259 260 261 262 263 264
                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 已提交
265
  auto b = a.Clone();
Y
Yu Yang 已提交
266
  ASSERT_EQ(a.Type(), b->Type());
267
}