ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
SparseConv.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #pragma once
9 #include <tbb/parallel_for.h>
10 
11 #include <Eigen/Core>
12 
13 namespace cloudViewer {
14 namespace ml {
15 namespace impl {
16 
19 template <class TFeat,
20  class TOut,
21  class TIndex,
22  class TKernelIndex,
23  bool POINT_IMPORTANCE>
24 void _SparseConvComputeFeaturesCPU(TOut* out_features,
25  const std::vector<int>& filter_dims,
26  const TFeat* filter,
27  size_t num_out,
28  size_t num_inp,
29  const TFeat* inp_features,
30  const TFeat* inp_importance,
31  size_t neighbors_index_size,
32  const TIndex* neighbors_index,
33  const TKernelIndex* neighbors_kernel_index,
34  const TFeat* neighbors_importance,
35  const int64_t* neighbors_row_splits,
36  bool normalize) {
37  const bool NEIGHBOR_IMPORTANCE = neighbors_importance != nullptr;
38 
39  const int in_channels = filter_dims[filter_dims.size() - 2];
40  const int out_channels = filter_dims[filter_dims.size() - 1];
41 
42  int num_kernel_elements = 1;
43  for (std::size_t i = 0; i < filter_dims.size() - 2; ++i) {
44  num_kernel_elements *= filter_dims[i];
45  }
46 
47  memset(out_features, 0, sizeof(TOut) * num_out * out_channels);
48 
49  tbb::parallel_for(
50  tbb::blocked_range<size_t>(0, num_out, 32),
51  [&](const tbb::blocked_range<size_t>& r) {
52  int range_length = r.end() - r.begin();
53 
54  Eigen::Matrix<TOut, Eigen::Dynamic, 1> normalizers(range_length,
55  1);
56  normalizers.setZero();
57 
58  Eigen::Map<Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic>>
59  C(out_features + (r.begin() * out_channels),
60  out_channels, range_length);
61 
62  for (size_t out_idx = r.begin(); out_idx != r.end();
63  ++out_idx) {
64  const int out_col = out_idx - r.begin();
65  const size_t neighbor_start = neighbors_row_splits[out_idx];
66  const size_t neighbor_end =
67  neighbors_row_splits[out_idx + 1];
68 
69  for (size_t n = neighbor_start; n < neighbor_end; ++n) {
70  const size_t inp_idx = neighbors_index[n];
71  const int kernel_idx = neighbors_kernel_index[n];
72 
73  const TFeat n_importance =
74  (NEIGHBOR_IMPORTANCE ? neighbors_importance[n]
75  : TFeat(1));
76  normalizers(out_col) += TOut(n_importance);
77 
78  TFeat importance(1.0);
79  if (POINT_IMPORTANCE)
80  importance = inp_importance[inp_idx];
81  if (NEIGHBOR_IMPORTANCE) importance *= n_importance;
82 
83  Eigen::Map<const Eigen::Matrix<TFeat, Eigen::Dynamic,
84  Eigen::Dynamic>>
85  A(filter + kernel_idx * out_channels *
86  in_channels,
87  out_channels, in_channels);
88 
89  Eigen::Map<const Eigen::Matrix<TFeat, Eigen::Dynamic,
90  Eigen::Dynamic>>
91  B(inp_features + inp_idx * in_channels,
92  in_channels, 1);
93 
94  C.col(out_col) +=
95  (A * (importance * B)).template cast<TOut>();
96  }
97 
98  } // out_idx
99 
100  if (normalize) {
101  for (int i = 0; i < range_length; ++i) {
102  if (normalizers(i) != TOut(0))
103  C.col(i) /= normalizers(i);
104  }
105  }
106  });
107 }
108 
154 template <class TFeat, class TOut, class TIndex, class TKernelIndex>
155 void SparseConvComputeFeaturesCPU(TOut* out_features,
156  const std::vector<int>& filter_dims,
157  const TFeat* filter,
158  size_t num_out,
159  size_t num_inp,
160  const TFeat* inp_features,
161  const TFeat* inp_importance,
162  size_t neighbors_index_size,
163  const TIndex* neighbors_index,
164  const TKernelIndex* neighbors_kernel_index,
165  const TFeat* neighbors_importance,
166  const int64_t* neighbors_row_splits,
167  bool normalize) {
168  // Dispatch all template parameter combinations
169  bool has_importance = inp_importance;
170 
171 #define FN_PARAMETERS \
172  out_features, filter_dims, filter, num_out, num_inp, inp_features, \
173  inp_importance, neighbors_index_size, neighbors_index, \
174  neighbors_kernel_index, neighbors_importance, \
175  neighbors_row_splits, normalize
176 
177 #define CALL_TEMPLATE(HAS_IMPORTANCE) \
178  if (HAS_IMPORTANCE == has_importance) \
179  _SparseConvComputeFeaturesCPU<TFeat, TOut, TIndex, TKernelIndex, \
180  HAS_IMPORTANCE>(FN_PARAMETERS);
181 
182 #define CALL_TEMPLATE2 \
183  CALL_TEMPLATE(true) \
184  CALL_TEMPLATE(false)
185 
187 
188 #undef CALL_TEMPLATE
189 #undef CALL_TEMPLATE2
190 
191 #undef FN_PARAMETERS
192 }
193 
194 } // namespace impl
195 } // namespace ml
196 } // namespace cloudViewer
#define CALL_TEMPLATE2
__host__ __device__ float2 normalize(float2 v)
Definition: cutil_math.h:1179
void SparseConvComputeFeaturesCPU(TOut *out_features, const std::vector< int > &filter_dims, const TFeat *filter, size_t num_out, size_t num_inp, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TKernelIndex *neighbors_kernel_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, bool normalize)
Definition: SparseConv.h:155
void _SparseConvComputeFeaturesCPU(TOut *out_features, const std::vector< int > &filter_dims, const TFeat *filter, size_t num_out, size_t num_inp, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TKernelIndex *neighbors_kernel_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, bool normalize)
Definition: SparseConv.h:24
Generic file read and write utility for python interface.