small_gicp
kdtree_omp.hpp
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright 2024 Kenji Koide
2 // SPDX-License-Identifier: MIT
3 #pragma once
4 
5 #include <atomic>
7 
8 #ifdef _MSC_VER
9 #pragma message("warning: Task-based OpenMP parallelism causes run-time memory errors with Eigen matrices.")
10 #pragma message("warning: Thus, OpenMP-based multi-threading for KdTree construction is disabled on MSVC.")
11 #endif
12 
13 namespace small_gicp {
14 
17 public:
21 
23  template <typename KdTree, typename PointCloud>
24  void build_tree(KdTree& kdtree, const PointCloud& points) const {
25  kdtree.indices.resize(traits::size(points));
26  std::iota(kdtree.indices.begin(), kdtree.indices.end(), 0);
27 
28  std::atomic_uint64_t node_count = 0;
29  kdtree.nodes.resize(traits::size(points));
30 
31 #ifndef _MSC_VER
32 #pragma omp parallel num_threads(num_threads)
33  {
34 #pragma omp single nowait
35  { kdtree.root = create_node(kdtree, node_count, points, kdtree.indices.begin(), kdtree.indices.begin(), kdtree.indices.end()); }
36  }
37 #else
38  kdtree.root = create_node(kdtree, node_count, points, kdtree.indices.begin(), kdtree.indices.begin(), kdtree.indices.end());
39 #endif
40 
41  kdtree.nodes.resize(node_count);
42  }
43 
49  template <typename PointCloud, typename KdTree, typename IndexConstIterator>
51  KdTree& kdtree,
52  std::atomic_uint64_t& node_count,
53  const PointCloud& points,
54  IndexConstIterator global_first,
55  IndexConstIterator first,
56  IndexConstIterator last) const {
57  const size_t N = std::distance(first, last);
58  const NodeIndexType node_index = node_count++;
59  auto& node = kdtree.nodes[node_index];
60 
61  // Create a leaf node.
62  if (N <= max_leaf_size) {
63  // std::sort(first, last);
64  node.node_type.lr.first = std::distance(global_first, first);
65  node.node_type.lr.last = std::distance(global_first, last);
66 
67  return node_index;
68  }
69 
70  // Find the best axis to split the input points.
71  using Projection = typename KdTree::Projection;
72  const auto proj = Projection::find_axis(points, first, last, projection_setting);
73  const auto median_itr = first + N / 2;
74  std::nth_element(first, median_itr, last, [&](size_t i, size_t j) { return proj(traits::point(points, i)) < proj(traits::point(points, j)); });
75 
76  // Create a non-leaf node.
77  node.node_type.sub.proj = proj;
78  node.node_type.sub.thresh = proj(traits::point(points, *median_itr));
79 
80  // Create left and right child nodes.
81 #ifndef _MSC_VER
82 #pragma omp task default(shared) if (N > 512)
83  node.left = create_node(kdtree, node_count, points, global_first, first, median_itr);
84 #pragma omp task default(shared) if (N > 512)
85  node.right = create_node(kdtree, node_count, points, global_first, median_itr, last);
86 #pragma omp taskwait
87 #else
88  node.left = create_node(kdtree, node_count, points, global_first, first, median_itr);
89  node.right = create_node(kdtree, node_count, points, global_first, median_itr, last);
90 #endif
91 
92  return node_index;
93  }
94 
95 public:
99 };
100 
101 } // namespace small_gicp
size_t size(const T &points)
Get the number of points.
Definition: traits.hpp:16
auto point(const T &points, size_t i)
Get i-th point. 4D vector is used to take advantage of SIMD intrinsics. The last element must be fill...
Definition: traits.hpp:40
Definition: flat_container.hpp:12
std::uint32_t NodeIndexType
Definition: kdtree.hpp:52
Kd-tree builder with OpenMP.
Definition: kdtree_omp.hpp:16
int max_leaf_size
Maximum number of points in a leaf node.
Definition: kdtree_omp.hpp:97
KdTreeBuilderOMP(int num_threads=4)
Constructor.
Definition: kdtree_omp.hpp:20
int num_threads
Number of threads.
Definition: kdtree_omp.hpp:96
void build_tree(KdTree &kdtree, const PointCloud &points) const
Build KdTree.
Definition: kdtree_omp.hpp:24
NodeIndexType create_node(KdTree &kdtree, std::atomic_uint64_t &node_count, const PointCloud &points, IndexConstIterator global_first, IndexConstIterator first, IndexConstIterator last) const
Create a Kd-tree node from the given point indices.
Definition: kdtree_omp.hpp:50
ProjectionSetting projection_setting
Projection setting.
Definition: kdtree_omp.hpp:98
"Safe" KdTree that holds the ownership of the input points.
Definition: kdtree.hpp:245
Point cloud.
Definition: point_cloud.hpp:15
Parameters to control the projection axis search.
Definition: projection.hpp:12