Caffe2 - C++ API
A deep learning, cross platform ML framework
test_utils.h
1 #ifndef CAFFE2_UTILS_TEST_UTILS_H_
2 #define CAFFE2_UTILS_TEST_UTILS_H_
3 
4 #include "caffe2/core/tensor.h"
5 #include "caffe2/core/workspace.h"
6 #include "caffe2/utils/proto_utils.h"
7 
8 #include <cmath>
9 #include <string>
10 #include <vector>
11 
12 // Utilities that make it easier to write caffe2 C++ unit tests.
13 // These utils are designed to be concise and easy to use. They may sacrifice
14 // performance and should only be used in tests/non production code.
15 namespace caffe2 {
16 namespace testing {
17 
18 // Asserts that the values of two tensors are the same.
19 void assertTensorEquals(const TensorCPU& tensor1, const TensorCPU& tensor2);
20 
21 // Asserts that two float values are close within epsilon.
22 void assertNear(float value1, float value2, float epsilon);
23 
24 // Asserts that the numeric values of a tensor is equal to a data vector.
25 template <typename T>
26 void assertTensorEquals(
27  const TensorCPU& tensor,
28  const std::vector<T>& data,
29  float epsilon = 0.1f) {
30  CAFFE_ENFORCE(tensor.IsType<T>());
31  CAFFE_ENFORCE_EQ(tensor.numel(), data.size());
32  for (auto idx = 0; idx < tensor.numel(); ++idx) {
33  if (tensor.IsType<float>()) {
34  assertNear(tensor.data<T>()[idx], data[idx], epsilon);
35  } else {
36  CAFFE_ENFORCE_EQ(tensor.data<T>()[idx], data[idx]);
37  }
38  }
39 }
40 
41 // Assertion for tensor sizes and values.
42 template <typename T>
43 void assertTensor(
44  const TensorCPU& tensor,
45  const std::vector<int64_t>& sizes,
46  const std::vector<T>& data,
47  float epsilon = 0.1f) {
48  CAFFE_ENFORCE_EQ(tensor.sizes(), sizes);
49  assertTensorEquals(tensor, data, epsilon);
50 }
51 
52 // Asserts a list of tensors presented in two workspaces are equal.
53 void assertTensorListEquals(
54  const std::vector<std::string>& tensorNames,
55  const Workspace& workspace1,
56  const Workspace& workspace2);
57 
58 // Read a tensor from the workspace.
59 const caffe2::Tensor& getTensor(
60  const caffe2::Workspace& workspace,
61  const std::string& name);
62 
63 // Create a new tensor in the workspace.
64 caffe2::Tensor* createTensor(
65  const std::string& name,
66  caffe2::Workspace* workspace);
67 
68 // Create a new operator in the net.
69 caffe2::OperatorDef* createOperator(
70  const std::string& type,
71  const std::vector<std::string>& inputs,
72  const std::vector<std::string>& outputs,
73  caffe2::NetDef* net);
74 
75 // Fill data from a vector to a tensor.
76 template <typename T>
77 void fillTensor(
78  const std::vector<int64_t>& shape,
79  const std::vector<T>& data,
80  TensorCPU* tensor) {
81  tensor->Resize(shape);
82  CAFFE_ENFORCE_EQ(data.size(), tensor->numel());
83  auto ptr = tensor->mutable_data<T>();
84  for (int i = 0; i < tensor->numel(); ++i) {
85  ptr[i] = data[i];
86  }
87 }
88 
89 // Create a tensor and fill data.
90 template <typename T>
91 caffe2::Tensor* createTensorAndFill(
92  const std::string& name,
93  const std::vector<int64_t>& shape,
94  const std::vector<T>& data,
95  Workspace* workspace) {
96  auto* tensor = createTensor(name, workspace);
97  fillTensor<T>(shape, data, tensor);
98  return tensor;
99 }
100 
101 // Fill a constant to a tensor.
102 template <typename T>
103 void constantFillTensor(
104  const vector<int64_t>& shape,
105  const T& data,
106  TensorCPU* tensor) {
107  tensor->Resize(shape);
108  auto ptr = tensor->mutable_data<T>();
109  for (int i = 0; i < tensor->numel(); ++i) {
110  ptr[i] = data;
111  }
112 }
113 
114 // Create a tensor and fill a constant.
115 template <typename T>
116 caffe2::Tensor* createTensorAndConstantFill(
117  const std::string& name,
118  const std::vector<int64_t>& shape,
119  const T& data,
120  Workspace* workspace) {
121  auto* tensor = createTensor(name, workspace);
122  constantFillTensor<T>(shape, data, tensor);
123  return tensor;
124 }
125 
126 // Concise util class to mutate a net in a chaining fashion.
127 class CAFFE2_API NetMutator {
128  public:
129  explicit NetMutator(caffe2::NetDef* net) : net_(net) {}
130 
131  NetMutator& newOp(
132  const std::string& type,
133  const std::vector<std::string>& inputs,
134  const std::vector<std::string>& outputs);
135 
136  NetMutator& externalInputs(const std::vector<std::string>& externalInputs);
137 
138  NetMutator& externalOutputs(const std::vector<std::string>& externalOutputs);
139 
140  // Add argument to the last created op.
141  template <typename T>
142  NetMutator& addArgument(const std::string& name, const T& value) {
143  CAFFE_ENFORCE(lastCreatedOp_ != nullptr);
144  AddArgument(name, value, lastCreatedOp_);
145  return *this;
146  }
147 
148  // Set device name for the last created op.
149  NetMutator& setDeviceOptionName(const std::string& name);
150 
151  private:
152  caffe2::NetDef* net_;
153  caffe2::OperatorDef* lastCreatedOp_;
154 };
155 
156 // Concise util class to mutate a workspace in a chaining fashion.
158  public:
159  explicit WorkspaceMutator(caffe2::Workspace* workspace)
160  : workspace_(workspace) {}
161 
162  // New tensor filled by a data vector.
163  template <typename T>
164  WorkspaceMutator& newTensor(
165  const std::string& name,
166  const std::vector<int64_t>& shape,
167  const std::vector<T>& data) {
168  createTensorAndFill<T>(name, shape, data, workspace_);
169  return *this;
170  }
171 
172  // New tensor filled by a constant.
173  template <typename T>
174  WorkspaceMutator& newTensorConst(
175  const std::string& name,
176  const std::vector<int64_t>& shape,
177  const T& data) {
178  createTensorAndConstantFill<T>(name, shape, data, workspace_);
179  return *this;
180  }
181 
182  private:
183  caffe2::Workspace* workspace_;
184 };
185 
186 } // namespace testing
187 } // namespace caffe2
188 
189 #endif // CAFFE2_UTILS_TEST_UTILS_H_
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13