Caffe2 - C++ API
A deep learning, cross platform ML framework
elementwise_op_test.h
1 #ifndef CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
2 #define CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
3 
4 #include "caffe2/operators/elementwise_ops.h"
5 
6 #include <iostream>
7 #include <string>
8 #include <vector>
9 
10 #include <gtest/gtest.h>
11 
12 template <typename Context, typename T>
13 void CopyVector(const int N, const T* x, T* y);
14 
15 template <typename Context, typename I_Type, typename O_Type>
16 void FillTensor(
18  const std::string& name,
19  const std::vector<int64_t>& shape,
20  const std::vector<I_Type>& values) {
21  auto* blob = ws->CreateBlob(name);
22  auto* tensor = BlobGetMutableTensor(blob, Context::GetDeviceType());
23  tensor->Resize(shape);
24  auto* mutable_data = tensor->template mutable_data<O_Type>();
25  const O_Type* data = reinterpret_cast<const O_Type*>(values.data());
26  CopyVector<Context, O_Type>(values.size(), data, mutable_data);
27 }
28 
29 template <typename Context>
30 caffe2::OperatorDef CreateOperatorDef() {
31  caffe2::OperatorDef def;
32  return def;
33 }
34 
35 template <typename Context>
36 caffe2::OperatorDef DefineOperator(const std::string& op_type) {
37  caffe2::OperatorDef def = CreateOperatorDef<Context>();
38  def.set_name("test");
39  def.set_type(op_type);
40  def.add_input("X");
41  def.add_input("Y");
42  def.add_output("Z");
43  return def;
44 }
45 
46 template <typename Context>
47 void elementwiseAnd() {
48  const int N = 4;
49  const int M = 2;
51  auto def = DefineOperator<Context>("And");
52  { // equal size
53  FillTensor<Context, uint8_t, bool>(
54  &ws, "X", {N}, {true, false, true, false});
55  FillTensor<Context, uint8_t, bool>(
56  &ws, "Y", {N}, {true, true, false, false});
57  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
58  EXPECT_NE(nullptr, op.get());
59  EXPECT_TRUE(op->Run());
60  auto* blob = ws.GetBlob("Z");
61  EXPECT_NE(nullptr, blob);
62  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
63  EXPECT_EQ(Z.numel(), N);
64  std::vector<bool> result{true, false, false, false};
65  for (size_t i = 0; i < Z.numel(); ++i) {
66  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
67  }
68  }
69  { // broadcast
70  auto* arg = def.add_arg();
71  arg->set_name("broadcast");
72  arg->set_i(1);
73  FillTensor<Context, uint8_t, bool>(
74  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
75  FillTensor<Context, uint8_t, bool>(
76  &ws, "Y", {N}, {true, true, false, false});
77  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
78  EXPECT_NE(nullptr, op.get());
79  EXPECT_TRUE(op->Run());
80  auto* blob = ws.GetBlob("Z");
81  EXPECT_NE(nullptr, blob);
82  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
83  EXPECT_EQ(Z.numel(), M * N);
84  std::vector<bool> result{
85  true, false, false, false, true, false, false, false};
86  for (size_t i = 0; i < Z.numel(); ++i) {
87  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
88  }
89  }
90 }
91 
92 template <typename Context>
93 void elementwiseOr() {
94  const int N = 4;
95  const int M = 2;
97  auto def = DefineOperator<Context>("Or");
98  { // equal size
99  FillTensor<Context, uint8_t, bool>(
100  &ws, "X", {N}, {true, false, true, false});
101  FillTensor<Context, uint8_t, bool>(
102  &ws, "Y", {N}, {true, true, false, false});
103  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
104  EXPECT_NE(nullptr, op.get());
105  EXPECT_TRUE(op->Run());
106  auto* blob = ws.GetBlob("Z");
107  EXPECT_NE(nullptr, blob);
108  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
109  EXPECT_EQ(Z.numel(), N);
110  std::vector<bool> result{true, true, true, false};
111  for (size_t i = 0; i < Z.numel(); ++i) {
112  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
113  }
114  }
115  { // broadcast
116  auto* arg = def.add_arg();
117  arg->set_name("broadcast");
118  arg->set_i(1);
119  FillTensor<Context, uint8_t, bool>(
120  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
121  FillTensor<Context, uint8_t, bool>(
122  &ws, "Y", {N}, {true, true, false, false});
123  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
124  EXPECT_NE(nullptr, op.get());
125  EXPECT_TRUE(op->Run());
126  auto* blob = ws.GetBlob("Z");
127  EXPECT_NE(nullptr, blob);
128  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
129  EXPECT_EQ(Z.numel(), M * N);
130  std::vector<bool> result{true, true, true, false, true, true, true, false};
131  for (size_t i = 0; i < Z.numel(); ++i) {
132  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
133  }
134  }
135 }
136 
137 template <typename Context>
138 void elementwiseXor() {
139  const int N = 4;
140  const int M = 2;
142  auto def = DefineOperator<Context>("Xor");
143  { // equal size
144  FillTensor<Context, uint8_t, bool>(
145  &ws, "X", {N}, {true, false, true, false});
146  FillTensor<Context, uint8_t, bool>(
147  &ws, "Y", {N}, {true, true, false, false});
148  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
149  EXPECT_NE(nullptr, op.get());
150  EXPECT_TRUE(op->Run());
151  auto* blob = ws.GetBlob("Z");
152  EXPECT_NE(nullptr, blob);
153  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
154  EXPECT_EQ(Z.numel(), N);
155  std::vector<bool> result{false, true, true, false};
156  for (size_t i = 0; i < Z.numel(); ++i) {
157  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
158  }
159  }
160  { // broadcast
161  auto* arg = def.add_arg();
162  arg->set_name("broadcast");
163  arg->set_i(1);
164  FillTensor<Context, uint8_t, bool>(
165  &ws, "X", {M, N}, {true, false, true, false, true, false, true, false});
166  FillTensor<Context, uint8_t, bool>(
167  &ws, "Y", {N}, {true, true, false, false});
168  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
169  EXPECT_NE(nullptr, op.get());
170  EXPECT_TRUE(op->Run());
171  auto* blob = ws.GetBlob("Z");
172  EXPECT_NE(nullptr, blob);
173  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
174  EXPECT_EQ(Z.numel(), M * N);
175  std::vector<bool> result{
176  false, true, true, false, false, true, true, false};
177  for (size_t i = 0; i < Z.numel(); ++i) {
178  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
179  }
180  }
181 }
182 
183 template <typename Context>
184 void elementwiseNot() {
185  const int N = 2;
187  caffe2::OperatorDef def = CreateOperatorDef<Context>();
188  def.set_name("test");
189  def.set_type("Not");
190  def.add_input("X");
191  def.add_output("Y");
192  FillTensor<Context, uint8_t, bool>(&ws, "X", {N}, {true, false});
193  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
194  EXPECT_NE(nullptr, op.get());
195  EXPECT_TRUE(op->Run());
196  auto* blob = ws.GetBlob("Y");
197  EXPECT_NE(nullptr, blob);
198  caffe2::Tensor Y(blob->Get<caffe2::Tensor>(), caffe2::CPU);
199  EXPECT_EQ(Y.numel(), N);
200  std::vector<bool> result{false, true};
201  for (size_t i = 0; i < Y.numel(); ++i) {
202  EXPECT_EQ(Y.template data<bool>()[i], result[i]);
203  }
204 }
205 
206 template <typename Context>
207 void elementwiseEQ() {
208  const int N = 4;
209  const int M = 2;
211  auto def = DefineOperator<Context>("EQ");
212  { // equal size
213  FillTensor<Context, int32_t, int32_t>(&ws, "X", {N}, {1, 100, 5, -10});
214  FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {0, 100, 4, -10});
215  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
216  EXPECT_NE(nullptr, op.get());
217  EXPECT_TRUE(op->Run());
218  auto* blob = ws.GetBlob("Z");
219  EXPECT_NE(nullptr, blob);
220  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
221  EXPECT_EQ(Z.numel(), N);
222  std::vector<bool> result{false, true, false, true};
223  for (size_t i = 0; i < Z.numel(); ++i) {
224  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
225  }
226  }
227  { // boolean
228  FillTensor<Context, uint8_t, bool>(
229  &ws, "X", {N}, {true, false, false, true});
230  FillTensor<Context, uint8_t, bool>(
231  &ws, "Y", {N}, {true, false, true, false});
232  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
233  EXPECT_NE(nullptr, op.get());
234  EXPECT_TRUE(op->Run());
235  auto* blob = ws.GetBlob("Z");
236  EXPECT_NE(nullptr, blob);
237  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
238  EXPECT_EQ(Z.numel(), N);
239  std::vector<bool> result{true, true, false, false};
240  for (size_t i = 0; i < Z.numel(); ++i) {
241  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
242  }
243  }
244  { // broadcast
245  auto* arg = def.add_arg();
246  arg->set_name("broadcast");
247  arg->set_i(1);
248  FillTensor<Context, int32_t, int32_t>(
249  &ws, "X", {M, N}, {1, 100, 5, -10, 3, 6, -1000, 33});
250  FillTensor<Context, int32_t, int32_t>(&ws, "Y", {N}, {1, 6, -1000, -10});
251  std::unique_ptr<caffe2::OperatorBase> op(caffe2::CreateOperator(def, &ws));
252  EXPECT_NE(nullptr, op.get());
253  EXPECT_TRUE(op->Run());
254  auto* blob = ws.GetBlob("Z");
255  EXPECT_NE(nullptr, blob);
256  caffe2::Tensor Z(blob->Get<caffe2::Tensor>(), caffe2::CPU);
257  EXPECT_EQ(Z.numel(), M * N);
258  std::vector<bool> result{
259  true, false, false, true, false, true, true, false};
260  for (size_t i = 0; i < Z.numel(); ++i) {
261  EXPECT_EQ(Z.template data<bool>()[i], result[i]);
262  }
263  }
264 }
265 
266 #endif // CAFFE2_OPERATORS_ELEMENTWISE_OP_TEST_H_
Blob * CreateBlob(const string &name)
Creates a blob of the given name.
Definition: workspace.cc:100
Definition: any.cpp:108
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47