Open3D (C++ API)  0.18.0
SparseConvTransposeBackpropFilter.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2023 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 #include <tbb/parallel_for.h>
10 
11 #include <Eigen/Core>
12 #include <mutex>
13 
14 namespace open3d {
15 namespace ml {
16 namespace impl {
17 
20 template <class TFeat,
21  class TOut,
22  class TIndex,
23  class TKernelIndex,
24  bool NORMALIZE>
26  TOut* filter_backprop,
27  const std::vector<int>& filter_dims,
28  size_t num_out,
29  const TFeat* out_importance,
30  size_t num_inp,
31  const TFeat* inp_features,
32  const TFeat* inp_neighbors_importance_sum,
33  const int64_t* inp_neighbors_row_splits,
34  const TIndex* neighbors_index,
35  const TKernelIndex* neighbors_kernel_index,
36  const TFeat* neighbors_importance,
37  const int64_t* neighbors_row_splits,
38  const TFeat* out_features_gradient) {
39  const bool NEIGHBOR_IMPORTANCE = neighbors_importance;
40 
41  const int in_channels = filter_dims[filter_dims.size() - 2];
42  const int out_channels = filter_dims[filter_dims.size() - 1];
43 
44  int num_kernel_elements = 1;
45  for (int i = 0; i < filter_dims.size() - 2; ++i)
46  num_kernel_elements *= filter_dims[i];
47 
48  memset(filter_backprop, 0,
49  sizeof(TOut) * num_kernel_elements * in_channels * out_channels);
50  std::mutex filter_backprop_mutex;
51 
52  tbb::parallel_for(
53  tbb::blocked_range<size_t>(0, num_out, 32),
54  [&](const tbb::blocked_range<size_t>& r) {
55  int range_length = r.end() - r.begin();
56 
57  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> B(
58  in_channels * num_kernel_elements, range_length);
59  B.setZero();
60  Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> C(
61  out_channels, range_length);
62 
63  Eigen::Array<TFeat, Eigen::Dynamic, 1> infeat(in_channels, 1);
64 
65  for (size_t out_idx = r.begin(); out_idx != r.end();
66  ++out_idx) {
67  const int out_col = out_idx - r.begin();
68  const size_t neighbor_start = neighbors_row_splits[out_idx];
69  const size_t neighbor_end =
70  neighbors_row_splits[out_idx + 1];
71 
72  C.col(out_col) = Eigen::Map<
73  const Eigen::Array<TFeat, Eigen::Dynamic, 1>>(
74  out_features_gradient + out_idx * out_channels,
75  out_channels, 1);
76 
77  for (size_t n = neighbor_start; n < neighbor_end; ++n) {
78  const size_t inp_idx = neighbors_index[n];
79  const int kernel_idx = neighbors_kernel_index[n];
80 
81  TFeat n_importance = NEIGHBOR_IMPORTANCE
82  ? neighbors_importance[n]
83  : TFeat(1);
84  for (int ic = 0; ic < in_channels; ++ic)
85  infeat(ic) =
86  inp_features[inp_idx * in_channels + ic] *
87  n_importance;
88 
89  if (NORMALIZE) {
90  TFeat normalizer(1);
91  if (NEIGHBOR_IMPORTANCE) {
92  if (inp_neighbors_importance_sum[inp_idx] !=
93  TFeat(0))
94  normalizer /= inp_neighbors_importance_sum
95  [inp_idx];
96  } else {
97  size_t num_inp_neighbors;
98  const size_t inp_neighbor_start =
99  inp_neighbors_row_splits[inp_idx];
100  const size_t inp_neighbor_end =
101  inp_neighbors_row_splits[inp_idx + 1];
102  num_inp_neighbors =
103  inp_neighbor_end - inp_neighbor_start;
104  if (num_inp_neighbors > 0)
105  normalizer /= TFeat(num_inp_neighbors);
106  }
107  for (int ic = 0; ic < in_channels; ++ic)
108  infeat(ic) *= normalizer;
109  }
110 
111  for (int ic = 0; ic < in_channels; ++ic) {
112  B(kernel_idx * in_channels + ic, out_col) +=
113  infeat(ic);
114  }
115  }
116 
117  } // out_idx
118 
119  if (out_importance) {
120  for (size_t out_idx = r.begin(); out_idx != r.end();
121  ++out_idx) {
122  const int out_col = out_idx - r.begin();
123  C.col(out_col) *= out_importance[out_idx];
124  }
125  }
126 
127  Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic> A(
128  out_channels, num_kernel_elements * in_channels);
129 
130  A = (C * B.transpose()).template cast<TOut>();
131 
132  {
133  std::lock_guard<std::mutex> lock(filter_backprop_mutex);
134  int linear_i = 0;
135  for (int j = 0; j < num_kernel_elements * in_channels; ++j)
136  for (int i = 0; i < out_channels; ++i, ++linear_i) {
137  filter_backprop[linear_i] += A(i, j);
138  }
139  }
140  });
141 }
142 
194 template <class TFeat, class TOut, class TIndex, class TKernelIndex>
196  TOut* filter_backprop,
197  const std::vector<int>& filter_dims,
198  size_t num_out,
199  const TFeat* out_importance,
200  size_t num_inp,
201  const TFeat* inp_features,
202  const TFeat* inp_neighbors_importance_sum,
203  const int64_t* inp_neighbors_row_splits,
204  const TIndex* neighbors_index,
205  const TKernelIndex* neighbors_kernel_index,
206  const TFeat* neighbors_importance,
207  const int64_t* neighbors_row_splits,
208  const TFeat* out_features_gradient,
209  bool normalize) {
210 #define FN_PARAMETERS \
211  filter_backprop, filter_dims, num_out, out_importance, num_inp, \
212  inp_features, inp_neighbors_importance_sum, \
213  inp_neighbors_row_splits, neighbors_index, neighbors_kernel_index, \
214  neighbors_importance, neighbors_row_splits, out_features_gradient
215 
216 #define CALL_TEMPLATE(NORMALIZE) \
217  if (NORMALIZE == normalize) \
218  _SparseConvTransposeBackpropFilterCPU<TFeat, TOut, TIndex, \
219  TKernelIndex, NORMALIZE>( \
220  FN_PARAMETERS);
221 
222 #define CALL_TEMPLATE2 \
223  CALL_TEMPLATE(true) \
224  CALL_TEMPLATE(false)
225 
227 
228 #undef CALL_TEMPLATE
229 #undef CALL_TEMPLATE2
230 
231 #undef FN_PARAMETERS
232 }
233 
234 } // namespace impl
235 } // namespace ml
236 } // namespace open3d
Eigen::Matrix3d B
Definition: PointCloudPlanarPatchDetection.cpp:506
#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:195
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:25
Definition: PinholeCameraIntrinsic.cpp:16