Caffe2 - C++ API
A deep learning, cross platform ML framework
reduction_ops.h
1 #ifndef CAFFE2_OPERATORS_REDUCTION_OPS_H_
2 #define CAFFE2_OPERATORS_REDUCTION_OPS_H_
3 
4 #include "caffe2/core/common_omp.h"
5 #include "caffe2/core/context.h"
6 #include "caffe2/core/logging.h"
7 #include "caffe2/core/operator.h"
8 #include "caffe2/utils/math.h"
9 
10 namespace caffe2 {
11 
12 template <typename T, class Context>
13 class SumElementsOp : public Operator<Context> {
14  public:
15  USE_OPERATOR_CONTEXT_FUNCTIONS;
16 
17  SumElementsOp(const OperatorDef& operator_def, Workspace* ws)
18  : Operator<Context>(operator_def, ws),
19  average_(OperatorBase::GetSingleArgument<bool>("average", false)) {}
20  SumElementsOp(const OperatorDef& operator_def, Workspace* ws, bool average)
21  : Operator<Context>(operator_def, ws), average_(average) {}
22  ~SumElementsOp() {}
23 
24  bool RunOnDevice() override
25 // TODO: T21635002 fix float-divide-by-zero undefined behavior
26 #if defined(__has_feature)
27 #if __has_feature(__address_sanitizer__)
28  __attribute__((__no_sanitize__("float-divide-by-zero")))
29 #endif
30 #endif
31  {
32  auto& X = Input(0);
33  auto* sum = Output(0);
34  sum->Resize(vector<TIndex>());
35  T* data = sum->template mutable_data<T>();
36  math::Sum<T, Context>(
37  X.size(), X.template data<T>(), data, &context_, &scratch_);
38  if (average_) {
39  math::Scale<T, Context>(
40  1,
41  static_cast<T>(1.) / X.size(),
42  sum->template data<T>(),
43  data,
44  &context_);
45  }
46  return true;
47  }
48 
49  private:
50  bool average_;
51  Tensor<Context> scratch_;
52 };
53 
54 template <typename T, class Context>
55 class SumElementsIntOp : public Operator<Context> {
56  public:
57  USE_OPERATOR_CONTEXT_FUNCTIONS;
58 
59  SumElementsIntOp(const OperatorDef& operator_def, Workspace* ws)
60  : Operator<Context>(operator_def, ws) {}
61  ~SumElementsIntOp() {}
62 
63  bool RunOnDevice() override {
64  auto& X = Input(0);
65  auto* sum = Output(0);
66  sum->Resize(vector<TIndex>());
67  T* data = sum->template mutable_data<T>();
68  math::Sum<T, Context>(
69  X.size(), X.template data<T>(), data, &context_, &scratch_);
70  return true;
71  }
72 
73  private:
74  Tensor<Context> scratch_;
75 };
76 
77 template <typename T, class Context>
78 class SumElementsGradientOp : public Operator<Context> {
79  public:
80  USE_OPERATOR_CONTEXT_FUNCTIONS;
81 
82  SumElementsGradientOp(const OperatorDef& operator_def, Workspace* ws)
83  : Operator<Context>(operator_def, ws),
84  average_(OperatorBase::GetSingleArgument<bool>("average", false)) {}
86  const OperatorDef& operator_def,
87  Workspace* ws,
88  bool average)
89  : Operator<Context>(operator_def, ws), average_(average) {}
91 
92  bool RunOnDevice() override;
93 
94  private:
95  bool average_;
96 };
97 
98 template <class Context>
99 class SumSqrElementsOp : public Operator<Context> {
100  public:
101  USE_SIMPLE_CTOR_DTOR(SumSqrElementsOp)
102  USE_OPERATOR_CONTEXT_FUNCTIONS;
103 
104  bool RunOnDevice() override {
105  return DispatchHelper<TensorTypes<float>>::call(this, Input(0));
106  }
107 
108  template <typename T>
109  bool DoRunWithType() {
110  bool average = OperatorBase::GetSingleArgument<bool>("average", false);
111  auto& X = Input(0);
112  auto* sum = Output(0);
113  sum->Resize(vector<TIndex>());
114  math::SumSqr<T, Context>(
115  X.size(),
116  X.template data<T>(),
117  sum->template mutable_data<T>(),
118  &context_,
119  &scratch_);
120  if (average) {
121  math::Scale<T, Context>(
122  1,
123  float(1.) / X.size(),
124  sum->template data<T>(),
125  sum->template mutable_data<T>(),
126  &context_);
127  }
128  return true;
129  }
130 
131  private:
132  Tensor<Context> scratch_;
133 };
134 
135 template <typename T, class Context, bool ROWWISE>
136 class MaxReductionOp : public Operator<Context> {
137  public:
138  USE_SIMPLE_CTOR_DTOR(MaxReductionOp)
139  USE_OPERATOR_CONTEXT_FUNCTIONS;
140 
141  bool RunOnDevice() override {
142  auto& X = Input(0);
143  CAFFE_ENFORCE_EQ(X.ndim(), 3);
144 
145  const int batch_size = X.dim32(0);
146  const int M = X.dim32(1);
147  const int N = X.dim32(2);
148 
149  auto* Y = Output(0);
150  ROWWISE ? Y->Resize(batch_size, M) : Y->Resize(batch_size, N);
151 
152  if (ROWWISE) {
153  math::RowwiseMax<T, Context>(
154  batch_size * M,
155  N,
156  X.template data<T>(),
157  Y->template mutable_data<T>(),
158  &context_);
159  } else {
160  const int input_size = N * M;
161  for (int i = 0; i < batch_size; ++i) {
162  math::ColwiseMax<T, Context>(
163  M,
164  N,
165  X.template data<T>() + i * input_size,
166  Y->template mutable_data<T>() + i * N,
167  &context_);
168  }
169  }
170  return true;
171  }
172 };
173 
174 template <typename T, class Context, bool ROWWISE>
175 class MaxReductionGradientOp : public Operator<Context> {
176  public:
177  USE_SIMPLE_CTOR_DTOR(MaxReductionGradientOp)
178  USE_OPERATOR_CONTEXT_FUNCTIONS;
179 
180  bool RunOnDevice() override;
181 };
182 
183 } // namespace caffe2
184 
185 #endif
Tensor is the basic class in Caffe2 that stores a contiguous memory with its shape information...
Definition: tensor.h:93
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 ...