Open3D (C++ API)  0.15.1
SparseConvBackpropFilter.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // The MIT License (MIT)
5 //
6 // Copyright (c) 2018-2021 www.open3d.org
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 #include <tbb/parallel_for.h>
29 
30 #include <Eigen/Core>
31 #include <mutex>
32 
33 namespace open3d {
34 namespace ml {
35 namespace impl {
36 
37 // Implementation of SparseConvBackropFilterCPU
38 template <class TFeat,
39  class TOut,
40  class TIndex,
41  class TKernelIndex,
42  bool POINT_IMPORTANCE>
43 void _SparseConvBackropFilterCPU(TOut* filter_backprop,
44  const std::vector<int>& filter_dims,
45  size_t num_out,
46  size_t num_inp,
47  const TFeat* inp_features,
48  const TFeat* inp_importance,
49  const TIndex* neighbors_index,
50  const TKernelIndex* neighbors_kernel_index,
51  const TFeat* neighbors_importance,
52  const int64_t* neighbors_row_splits,
53  const TFeat* out_features_gradient,
54  bool normalize) {
55  const bool NEIGHBOR_IMPORTANCE = neighbors_importance;
56 
57  const int in_channels = filter_dims[filter_dims.size() - 2];
58  const int out_channels = filter_dims[filter_dims.size() - 1];
59 
60  int num_kernel_elements = 1;
61  for (int i = 0; i < filter_dims.size() - 2; ++i)
62  num_kernel_elements *= filter_dims[i];
63  const int total_filter_size =
64  num_kernel_elements * in_channels * out_channels;
65 
66  memset(filter_backprop, 0, sizeof(TOut) * total_filter_size);
67  std::mutex filter_backprop_mutex;
68 
69  tbb::parallel_for(
70  tbb::blocked_range<size_t>(0, num_out, 10032),
71  [&](const tbb::blocked_range<size_t>& r) {
72  int range_length = r.end() - r.begin();
73 
74  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> B(
75  in_channels * num_kernel_elements, range_length);
76  B.setZero();
77  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> C(
78  out_channels, range_length);
79 
80  Eigen::Array<TFeat, Eigen::Dynamic, 1> infeat(in_channels, 1);
81 
82  for (size_t out_idx = r.begin(); out_idx != r.end();
83  ++out_idx) {
84  const int out_col = out_idx - r.begin();
85  const size_t neighbor_start = neighbors_row_splits[out_idx];
86  const size_t neighbor_end =
87  neighbors_row_splits[out_idx + 1];
88  TFeat normalizer(0);
89 
90  for (size_t n = neighbor_start; n < neighbor_end; ++n) {
91  const size_t inp_idx = neighbors_index[n];
92  const int kernel_idx = neighbors_kernel_index[n];
93 
94  const TFeat n_importance =
95  (NEIGHBOR_IMPORTANCE ? neighbors_importance[n]
96  : TFeat(1));
97  normalizer += n_importance;
98 
99  for (int ic = 0; ic < in_channels; ++ic)
100  infeat(ic) =
101  inp_features[inp_idx * in_channels + ic];
102 
103  TFeat importance(1);
104  if (POINT_IMPORTANCE)
105  importance = inp_importance[inp_idx];
106  if (NEIGHBOR_IMPORTANCE) importance *= n_importance;
107 
108  if (POINT_IMPORTANCE || NEIGHBOR_IMPORTANCE) {
109  for (int ic = 0; ic < in_channels; ++ic)
110  infeat(ic) *= importance;
111  }
112  for (int ic = 0; ic < in_channels; ++ic) {
113  B(kernel_idx * in_channels + ic, out_col) =
114  infeat(ic);
115  }
116  }
117 
118  C.col(out_col) = Eigen::Map<
119  const Eigen::Array<TFeat, Eigen::Dynamic, 1>>(
120  out_features_gradient + out_idx * out_channels,
121  out_channels, 1);
122 
123  if (normalize && normalizer != TFeat(0))
124  C.col(out_col) /= normalizer;
125 
126  } // out_idx
127 
128  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> A(
129  out_channels, num_kernel_elements * in_channels);
130 
131  A = C * B.transpose();
132 
133  {
134  std::lock_guard<std::mutex> lock(filter_backprop_mutex);
135  int linear_i = 0;
136  for (int j = 0; j < num_kernel_elements * in_channels; ++j)
137  for (int i = 0; i < out_channels; ++i, ++linear_i) {
138  filter_backprop[linear_i] += TOut(A(i, j));
139  }
140  }
141  });
142 }
143 
198 template <class TFeat, class TOut, class TIndex, class TKernelIndex>
199 void SparseConvBackpropFilterCPU(TOut* filter_backprop,
200  const std::vector<int>& filter_dims,
201  size_t num_out,
202  size_t num_inp,
203  const TFeat* inp_features,
204  const TFeat* inp_importance,
205  const TIndex* neighbors_index,
206  const TKernelIndex* neighbors_kernel_index,
207  const TFeat* neighbors_importance,
208  const int64_t* neighbors_row_splits,
209  const TFeat* out_features_gradient,
210  bool normalize) {
211  bool has_importance = inp_importance;
212 
213 #define FN_PARAMETERS \
214  filter_backprop, filter_dims, num_out, num_inp, inp_features, \
215  inp_importance, neighbors_index, neighbors_kernel_index, \
216  neighbors_importance, neighbors_row_splits, out_features_gradient, \
217  normalize
218 
219 #define CALL_TEMPLATE(HAS_IMPORTANCE) \
220  if (HAS_IMPORTANCE == has_importance) \
221  _SparseConvBackropFilterCPU<TFeat, TOut, TIndex, TKernelIndex, \
222  HAS_IMPORTANCE>(FN_PARAMETERS);
223 
224 #define CALL_TEMPLATE2 \
225  CALL_TEMPLATE(true) \
226  CALL_TEMPLATE(false)
227 
229 
230 #undef CALL_TEMPLATE
231 #undef CALL_TEMPLATE2
232 
233 #undef FN_PARAMETERS
234 }
235 
236 } // namespace impl
237 } // namespace ml
238 } // namespace open3d
#define CALL_TEMPLATE2
void _SparseConvBackropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, size_t num_inp, const TFeat *inp_features, const TFeat *inp_importance, const TIndex *neighbors_index, const TKernelIndex *neighbors_kernel_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TFeat *out_features_gradient, bool normalize)
Definition: SparseConvBackpropFilter.h:43
void SparseConvBackpropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, size_t num_inp, const TFeat *inp_features, const TFeat *inp_importance, const TIndex *neighbors_index, const TKernelIndex *neighbors_kernel_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TFeat *out_features_gradient, bool normalize)
Definition: SparseConvBackpropFilter.h:199
Definition: PinholeCameraIntrinsic.cpp:35