Open3D (C++ API)  0.15.1
SparseConvTransposeBackpropFilter.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 
39 template <class TFeat,
40  class TOut,
41  class TIndex,
42  class TKernelIndex,
43  bool NORMALIZE>
45  TOut* filter_backprop,
46  const std::vector<int>& filter_dims,
47  size_t num_out,
48  const TFeat* out_importance,
49  size_t num_inp,
50  const TFeat* inp_features,
51  const TFeat* inp_neighbors_importance_sum,
52  const int64_t* inp_neighbors_row_splits,
53  const TIndex* neighbors_index,
54  const TKernelIndex* neighbors_kernel_index,
55  const TFeat* neighbors_importance,
56  const int64_t* neighbors_row_splits,
57  const TFeat* out_features_gradient) {
58  const bool NEIGHBOR_IMPORTANCE = neighbors_importance;
59 
60  const int in_channels = filter_dims[filter_dims.size() - 2];
61  const int out_channels = filter_dims[filter_dims.size() - 1];
62 
63  int num_kernel_elements = 1;
64  for (int i = 0; i < filter_dims.size() - 2; ++i)
65  num_kernel_elements *= filter_dims[i];
66 
67  memset(filter_backprop, 0,
68  sizeof(TOut) * num_kernel_elements * in_channels * out_channels);
69  std::mutex filter_backprop_mutex;
70 
71  tbb::parallel_for(
72  tbb::blocked_range<size_t>(0, num_out, 32),
73  [&](const tbb::blocked_range<size_t>& r) {
74  int range_length = r.end() - r.begin();
75 
76  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> B(
77  in_channels * num_kernel_elements, range_length);
78  B.setZero();
79  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> C(
80  out_channels, range_length);
81 
82  Eigen::Array<TFeat, Eigen::Dynamic, 1> infeat(in_channels, 1);
83 
84  for (size_t out_idx = r.begin(); out_idx != r.end();
85  ++out_idx) {
86  const int out_col = out_idx - r.begin();
87  const size_t neighbor_start = neighbors_row_splits[out_idx];
88  const size_t neighbor_end =
89  neighbors_row_splits[out_idx + 1];
90 
91  C.col(out_col) = Eigen::Map<
92  const Eigen::Array<TFeat, Eigen::Dynamic, 1>>(
93  out_features_gradient + out_idx * out_channels,
94  out_channels, 1);
95 
96  for (size_t n = neighbor_start; n < neighbor_end; ++n) {
97  const size_t inp_idx = neighbors_index[n];
98  const int kernel_idx = neighbors_kernel_index[n];
99 
100  TFeat n_importance = NEIGHBOR_IMPORTANCE
101  ? neighbors_importance[n]
102  : TFeat(1);
103  for (int ic = 0; ic < in_channels; ++ic)
104  infeat(ic) =
105  inp_features[inp_idx * in_channels + ic] *
106  n_importance;
107 
108  if (NORMALIZE) {
109  TFeat normalizer(1);
110  if (NEIGHBOR_IMPORTANCE) {
111  if (inp_neighbors_importance_sum[inp_idx] !=
112  TFeat(0))
113  normalizer /= inp_neighbors_importance_sum
114  [inp_idx];
115  } else {
116  size_t num_inp_neighbors;
117  const size_t inp_neighbor_start =
118  inp_neighbors_row_splits[inp_idx];
119  const size_t inp_neighbor_end =
120  inp_neighbors_row_splits[inp_idx + 1];
121  num_inp_neighbors =
122  inp_neighbor_end - inp_neighbor_start;
123  if (num_inp_neighbors > 0)
124  normalizer /= TFeat(num_inp_neighbors);
125  }
126  for (int ic = 0; ic < in_channels; ++ic)
127  infeat(ic) *= normalizer;
128  }
129 
130  for (int ic = 0; ic < in_channels; ++ic) {
131  B(kernel_idx * in_channels + ic, out_col) +=
132  infeat(ic);
133  }
134  }
135 
136  } // out_idx
137 
138  if (out_importance) {
139  for (size_t out_idx = r.begin(); out_idx != r.end();
140  ++out_idx) {
141  const int out_col = out_idx - r.begin();
142  C.col(out_col) *= out_importance[out_idx];
143  }
144  }
145 
146  Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic> A(
147  out_channels, num_kernel_elements * in_channels);
148 
149  A = (C * B.transpose()).template cast<TOut>();
150 
151  {
152  std::lock_guard<std::mutex> lock(filter_backprop_mutex);
153  int linear_i = 0;
154  for (int j = 0; j < num_kernel_elements * in_channels; ++j)
155  for (int i = 0; i < out_channels; ++i, ++linear_i) {
156  filter_backprop[linear_i] += A(i, j);
157  }
158  }
159  });
160 }
161 
213 template <class TFeat, class TOut, class TIndex, class TKernelIndex>
215  TOut* filter_backprop,
216  const std::vector<int>& filter_dims,
217  size_t num_out,
218  const TFeat* out_importance,
219  size_t num_inp,
220  const TFeat* inp_features,
221  const TFeat* inp_neighbors_importance_sum,
222  const int64_t* inp_neighbors_row_splits,
223  const TIndex* neighbors_index,
224  const TKernelIndex* neighbors_kernel_index,
225  const TFeat* neighbors_importance,
226  const int64_t* neighbors_row_splits,
227  const TFeat* out_features_gradient,
228  bool normalize) {
229 #define FN_PARAMETERS \
230  filter_backprop, filter_dims, num_out, out_importance, num_inp, \
231  inp_features, inp_neighbors_importance_sum, \
232  inp_neighbors_row_splits, neighbors_index, neighbors_kernel_index, \
233  neighbors_importance, neighbors_row_splits, out_features_gradient
234 
235 #define CALL_TEMPLATE(NORMALIZE) \
236  if (NORMALIZE == normalize) \
237  _SparseConvTransposeBackpropFilterCPU<TFeat, TOut, TIndex, \
238  TKernelIndex, NORMALIZE>( \
239  FN_PARAMETERS);
240 
241 #define CALL_TEMPLATE2 \
242  CALL_TEMPLATE(true) \
243  CALL_TEMPLATE(false)
244 
246 
247 #undef CALL_TEMPLATE
248 #undef CALL_TEMPLATE2
249 
250 #undef FN_PARAMETERS
251 }
252 
253 } // namespace impl
254 } // namespace ml
255 } // namespace open3d
#define CALL_TEMPLATE2
void SparseConvTransposeBackpropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, const TFeat *out_importance, size_t num_inp, const TFeat *inp_features, const TFeat *inp_neighbors_importance_sum, const int64_t *inp_neighbors_row_splits, 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: SparseConvTransposeBackpropFilter.h:214
void _SparseConvTransposeBackpropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, const TFeat *out_importance, size_t num_inp, const TFeat *inp_features, const TFeat *inp_neighbors_importance_sum, const int64_t *inp_neighbors_row_splits, const TIndex *neighbors_index, const TKernelIndex *neighbors_kernel_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TFeat *out_features_gradient)
Definition: SparseConvTransposeBackpropFilter.h:44
Definition: PinholeCameraIntrinsic.cpp:35