10 #include <tbb/parallel_for.h>
21 template <
class TFeat,
28 bool INDIVIDUAL_EXTENT,
29 bool ISOTROPIC_EXTENT,
30 bool POINT_IMPORTANCE>
32 const std::vector<int>& filter_dims,
34 const TReal* out_positions,
36 const TReal* inp_positions,
37 const TFeat* inp_features,
38 const TFeat* inp_importance,
39 size_t neighbors_index_size,
40 const TIndex* neighbors_index,
41 const TFeat* neighbors_importance,
42 const int64_t* neighbors_row_splits,
45 const TFeat* out_features_gradient,
47 const bool NEIGHBORS_IMPORTANCE = neighbors_importance;
50 typedef Eigen::Array<TReal, VECSIZE, 1> Vec_t;
52 InterpolationVec_t interpolation;
54 const int in_channels = filter_dims[filter_dims.size() - 2];
55 const int out_channels = filter_dims[filter_dims.size() - 1];
57 int spatial_filter_size = 1;
58 for (
int i = 0; i < 3; ++i) spatial_filter_size *= filter_dims[i];
59 const int total_filter_size =
60 spatial_filter_size * in_channels * out_channels;
61 Eigen::Array<int, 3, 1> filter_size_xyz(filter_dims[2], filter_dims[1],
64 memset(filter_backprop, 0,
sizeof(TOut) * total_filter_size);
65 std::mutex filter_backprop_mutex;
67 typedef Eigen::Array<TFeat, VECSIZE, Eigen::Dynamic> Matrix;
68 typedef Eigen::Array<TReal, VECSIZE, 3> Matrix3C;
71 tbb::blocked_range<size_t>(0, num_out, 32),
72 [&](
const tbb::blocked_range<size_t>& r) {
73 int range_length = r.end() - r.begin();
75 Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> B(
76 in_channels * spatial_filter_size, range_length);
78 Eigen::Matrix<TFeat, Eigen::Dynamic, Eigen::Dynamic> C(
79 out_channels, range_length);
81 Matrix infeat(
VECSIZE, in_channels);
83 Eigen::Array<TReal, 3, 1> offsets_(offsets[0], offsets[1],
87 if (INDIVIDUAL_EXTENT ==
false) {
88 if (ISOTROPIC_EXTENT) {
89 inv_extents = 1 / extents[0];
91 inv_extents.col(0) = 1 / extents[0];
92 inv_extents.col(1) = 1 / extents[1];
93 inv_extents.col(2) = 1 / extents[2];
97 for (
size_t out_idx = r.begin(); out_idx != r.end();
99 const int out_col = out_idx - r.begin();
100 const size_t neighbor_start = neighbors_row_splits[out_idx];
101 const size_t neighbor_end =
102 neighbors_row_splits[out_idx + 1];
105 if (INDIVIDUAL_EXTENT) {
106 if (ISOTROPIC_EXTENT) {
107 inv_extents = 1 / extents[out_idx];
109 inv_extents.col(0) = 1 / extents[3 * out_idx + 0];
110 inv_extents.col(1) = 1 / extents[3 * out_idx + 1];
111 inv_extents.col(2) = 1 / extents[3 * out_idx + 2];
115 typename InterpolationVec_t::Weight_t interp_weights;
116 typename InterpolationVec_t::Idx_t interp_indices;
118 int vec_valid_count = 0;
126 for (
size_t n = neighbor_start; n < neighbor_end; ++n) {
127 const size_t inp_idx = neighbors_index[n];
128 const int i = vec_valid_count;
129 x(i) = inp_positions[inp_idx * 3 + 0] -
130 out_positions[out_idx * 3 + 0];
131 y(i) = inp_positions[inp_idx * 3 + 1] -
132 out_positions[out_idx * 3 + 1];
133 z(i) = inp_positions[inp_idx * 3 + 2] -
134 out_positions[out_idx * 3 + 2];
136 const TFeat n_importance =
137 (NEIGHBORS_IMPORTANCE ? neighbors_importance[n]
139 normalizer += TOut(n_importance);
141 for (
int ic = 0; ic < in_channels; ++ic)
143 inp_features[inp_idx * in_channels + ic];
145 TFeat importance = TFeat(1);
146 if (POINT_IMPORTANCE)
147 importance = inp_importance[inp_idx];
148 if (NEIGHBORS_IMPORTANCE) importance *= n_importance;
150 if (POINT_IMPORTANCE || NEIGHBORS_IMPORTANCE) {
151 for (
int ic = 0; ic < in_channels; ++ic)
152 infeat(i, ic) *= importance;
156 if (vec_valid_count ==
VECSIZE) {
159 x, y, z, filter_size_xyz, inv_extents,
161 interpolation.Interpolate(
162 interp_weights, interp_indices, x, y, z,
163 filter_size_xyz, in_channels);
164 for (
int k = 0; k <
VECSIZE; ++k)
165 for (
int j = 0; j < InterpolationVec_t::Size();
167 for (
int ic = 0; ic < in_channels; ++ic)
168 B(interp_indices(j, k) + ic, out_col) +=
169 TFeat(interp_weights(j, k)) *
175 if (vec_valid_count) {
178 x, y, z, filter_size_xyz, inv_extents,
180 interpolation.Interpolate(interp_weights,
181 interp_indices, x, y, z,
182 filter_size_xyz, in_channels);
183 for (
int k = 0; k < vec_valid_count; ++k)
184 for (
int j = 0; j < InterpolationVec_t::Size();
186 for (
int ic = 0; ic < in_channels; ++ic)
187 B(interp_indices(j, k) + ic, out_col) +=
188 TFeat(interp_weights(j, k)) *
193 C.col(out_col) = Eigen::Map<
194 const Eigen::Array<TFeat, Eigen::Dynamic, 1>>(
195 out_features_gradient + out_idx * out_channels,
199 C.col(out_col) /= TFeat(normalizer);
203 Eigen::Matrix<TOut, Eigen::Dynamic, Eigen::Dynamic> A(
204 out_channels, spatial_filter_size * in_channels);
206 A = (C * B.transpose()).
template cast<TOut>();
209 std::lock_guard<std::mutex> lock(filter_backprop_mutex);
211 for (
int j = 0; j < spatial_filter_size * in_channels; ++j)
212 for (
int i = 0; i < out_channels; ++i, ++linear_i) {
213 filter_backprop[linear_i] += A(i, j);
292 template <
class TFeat,
class TOut,
class TReal,
class TIndex>
294 const std::vector<int>& filter_dims,
296 const TReal* out_positions,
298 const TReal* inp_positions,
299 const TFeat* inp_features,
300 const TFeat* inp_importance,
301 size_t neighbors_index_size,
302 const TIndex* neighbors_index,
303 const TFeat* neighbors_importance,
304 const int64_t* neighbors_row_splits,
305 const TReal* extents,
306 const TReal* offsets,
307 const TFeat* out_features_gradient,
311 bool individual_extent,
312 bool isotropic_extent,
314 bool has_importance = inp_importance;
316 #define FN_PARAMETERS \
317 filter_backprop, filter_dims, num_out, out_positions, num_inp, \
318 inp_positions, inp_features, inp_importance, neighbors_index_size, \
319 neighbors_index, neighbors_importance, neighbors_row_splits, \
320 extents, offsets, out_features_gradient, normalize
322 #define CALL_TEMPLATE(INTERPOLATION, MAPPING, ALIGN_CORNERS, \
323 INDIVIDUAL_EXTENT, ISOTROPIC_EXTENT, HAS_IMPORTANCE) \
324 if (INTERPOLATION == interpolation && MAPPING == coordinate_mapping && \
325 ALIGN_CORNERS == align_corners && \
326 INDIVIDUAL_EXTENT == individual_extent && \
327 ISOTROPIC_EXTENT == isotropic_extent && \
328 HAS_IMPORTANCE == has_importance) \
329 _CConvBackropFilterCPU<TFeat, TOut, TReal, TIndex, INTERPOLATION, \
330 MAPPING, ALIGN_CORNERS, INDIVIDUAL_EXTENT, \
331 ISOTROPIC_EXTENT, HAS_IMPORTANCE>( \
334 #define CALL_TEMPLATE2(INTERPOLATION, MAPPING) \
335 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, true, true) \
336 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, true, false) \
337 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, false, true) \
338 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, true, false, false) \
339 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, true, true) \
340 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, true, false) \
341 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, false, true) \
342 CALL_TEMPLATE(INTERPOLATION, MAPPING, true, false, false, false) \
343 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, true, true) \
344 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, true, false) \
345 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, false, true) \
346 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, true, false, false) \
347 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, true, true) \
348 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, true, false) \
349 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, false, true) \
350 CALL_TEMPLATE(INTERPOLATION, MAPPING, false, false, false, false)
352 #define CALL_TEMPLATE3(INTERPOLATION) \
353 CALL_TEMPLATE2(INTERPOLATION, CoordinateMapping::BALL_TO_CUBE_RADIAL) \
354 CALL_TEMPLATE2(INTERPOLATION, \
355 CoordinateMapping::BALL_TO_CUBE_VOLUME_PRESERVING) \
356 CALL_TEMPLATE2(INTERPOLATION, CoordinateMapping::IDENTITY)
358 #define CALL_TEMPLATE4 \
359 CALL_TEMPLATE3(InterpolationMode::LINEAR) \
360 CALL_TEMPLATE3(InterpolationMode::LINEAR_BORDER) \
361 CALL_TEMPLATE3(InterpolationMode::NEAREST_NEIGHBOR)
366 #undef CALL_TEMPLATE2
367 #undef CALL_TEMPLATE3
368 #undef CALL_TEMPLATE4
__host__ __device__ float2 normalize(float2 v)
void _CConvBackropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, const TReal *out_positions, size_t num_inp, const TReal *inp_positions, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TReal *extents, const TReal *offsets, const TFeat *out_features_gradient, bool normalize)
void CConvBackpropFilterCPU(TOut *filter_backprop, const std::vector< int > &filter_dims, size_t num_out, const TReal *out_positions, size_t num_inp, const TReal *inp_positions, const TFeat *inp_features, const TFeat *inp_importance, size_t neighbors_index_size, const TIndex *neighbors_index, const TFeat *neighbors_importance, const int64_t *neighbors_row_splits, const TReal *extents, const TReal *offsets, const TFeat *out_features_gradient, InterpolationMode interpolation, CoordinateMapping coordinate_mapping, bool align_corners, bool individual_extent, bool isotropic_extent, bool normalize)
void ComputeFilterCoordinates(Eigen::Array< T, VECSIZE, 1 > &x, Eigen::Array< T, VECSIZE, 1 > &y, Eigen::Array< T, VECSIZE, 1 > &z, const Eigen::Array< int, 3, 1 > &filter_size, const Eigen::Array< T, VECSIZE, 3 > &inv_extents, const Eigen::Array< T, 3, 1 > &offset)
Generic file read and write utility for python interface.
Class for computing interpolation weights.