Open3D (C++ API)  0.16.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
33namespace open3d {
34namespace ml {
35namespace impl {
36
39template <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
213template <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