Skip to content

Commit

Permalink
Merge pull request #876 from aprokop/legacy_indexable_getter
Browse files Browse the repository at this point in the history
  • Loading branch information
aprokop committed Jun 9, 2023
2 parents ece4e6c + ba77769 commit 14d0cf3
Show file tree
Hide file tree
Showing 11 changed files with 180 additions and 91 deletions.
2 changes: 1 addition & 1 deletion src/ArborX_DBSCAN.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ dbscan(ExecutionSpace const &exec_space, Primitives const &primitives,
Kokkos::Profiling::pushRegion("ArborX::DBSCAN::dense_cells");
Box bounds;
Details::TreeConstruction::calculateBoundingBoxOfTheScene(
exec_space, primitives, bounds);
exec_space, Details::Indexables<Primitives>{primitives}, bounds);

// The cell length is chosen to be eps/sqrt(dimension), so that any two
// points within the same cell are within eps distance of each other.
Expand Down
25 changes: 16 additions & 9 deletions src/ArborX_LinearBVH.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <ArborX_DetailsTreeConstruction.hpp>
#include <ArborX_DetailsTreeTraversal.hpp>
#include <ArborX_HyperBox.hpp>
#include <ArborX_IndexableGetter.hpp>
#include <ArborX_SpaceFillingCurves.hpp>
#include <ArborX_TraversalPolicy.hpp>

Expand Down Expand Up @@ -105,6 +106,7 @@ class BasicBoundingVolumeHierarchy
bounding_volume_type _bounds;
Kokkos::View<leaf_node_type *, MemorySpace> _leaf_nodes;
Kokkos::View<internal_node_type *, MemorySpace> _internal_nodes;
Details::DefaultIndexableGetter _indexable_getter;
};

template <typename MemorySpace>
Expand Down Expand Up @@ -151,15 +153,17 @@ BasicBoundingVolumeHierarchy<MemorySpace, BoundingVolume>::

// determine the bounding box of the scene
ExperimentalHyperGeometry::Box<DIM> bbox{};
Details::TreeConstruction::calculateBoundingBoxOfTheScene(space, primitives,
bbox);
Details::TreeConstruction::calculateBoundingBoxOfTheScene(
space, Details::Indexables<Primitives>{primitives}, bbox);

Kokkos::Profiling::popRegion();

if (size() == 1)
{
Details::TreeConstruction::initializeSingleLeafNode(space, primitives,
_leaf_nodes);
Details::TreeConstruction::initializeSingleLeafNode(
space,
Details::LegacyValues<Primitives, bounding_volume_type>{primitives},
_leaf_nodes);
Kokkos::deep_copy(
space,
Kokkos::View<BoundingVolume, Kokkos::HostSpace,
Expand All @@ -171,7 +175,7 @@ BasicBoundingVolumeHierarchy<MemorySpace, BoundingVolume>::

Kokkos::Profiling::pushRegion("ArborX::BVH::BVH::compute_linear_ordering");

// map primitives from multidimensional domain to one-dimensional interval
// Map indexables from multidimensional domain to one-dimensional interval
using LinearOrderingValueType = Kokkos::detected_t<
Details::SpaceFillingCurveProjectionArchetypeExpression,
SpaceFillingCurve, decltype(bbox),
Expand All @@ -181,21 +185,24 @@ BasicBoundingVolumeHierarchy<MemorySpace, BoundingVolume>::
"ArborX::BVH::BVH::linear_ordering"),
size());
Details::TreeConstruction::projectOntoSpaceFillingCurve(
space, primitives, curve, bbox, linear_ordering_indices);
space, Details::Indexables<Primitives>{primitives}, curve, bbox,
linear_ordering_indices);

Kokkos::Profiling::popRegion();
Kokkos::Profiling::pushRegion("ArborX::BVH::BVH::sort_linearized_order");

// compute the ordering of the primitives along the space-filling curve
// Compute the ordering of the indexables along the space-filling curve
auto permutation_indices =
Details::sortObjects(space, linear_ordering_indices);

Kokkos::Profiling::popRegion();
Kokkos::Profiling::pushRegion("ArborX::BVH::BVH::generate_hierarchy");

// generate bounding volume hierarchy
// Generate bounding volume hierarchy
Details::TreeConstruction::generateHierarchy(
space, primitives, permutation_indices, linear_ordering_indices,
space,
Details::LegacyValues<Primitives, bounding_volume_type>{primitives},
_indexable_getter, permutation_indices, linear_ordering_indices,
_leaf_nodes, _internal_nodes);

Kokkos::deep_copy(
Expand Down
2 changes: 1 addition & 1 deletion src/details/ArborX_DetailsDistributedTreeImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ struct CallbackWithDistance
// need to be fixed with a proper callback abstraction.
int const leaf_node_index = _rev_permute(index);
auto const &leaf_node_bounding_volume =
HappyTreeFriends::getLeafBoundingVolume(_tree, leaf_node_index);
HappyTreeFriends::getIndexable(_tree, leaf_node_index);
out({index, distance(getGeometry(query), leaf_node_bounding_volume)});
}
};
Expand Down
9 changes: 4 additions & 5 deletions src/details/ArborX_DetailsHalfTraversal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,17 @@ struct HalfTraversal
KOKKOS_FUNCTION void operator()(int i) const
{
auto const predicate =
_get_predicate(HappyTreeFriends::getLeafBoundingVolume(_bvh, i));
_get_predicate(HappyTreeFriends::getIndexable(_bvh, i));
auto const leaf_permutation_i = HappyTreeFriends::getValue(_bvh, i).index;

int node = HappyTreeFriends::getRope(_bvh, i);
while (node != ROPE_SENTINEL)
{
bool const is_leaf = HappyTreeFriends::isLeaf(_bvh, node);

if (predicate(
(is_leaf
? HappyTreeFriends::getLeafBoundingVolume(_bvh, node)
: HappyTreeFriends::getInternalBoundingVolume(_bvh, node))))
if (predicate((is_leaf ? HappyTreeFriends::getIndexable(_bvh, node)
: HappyTreeFriends::getInternalBoundingVolume(
_bvh, node))))
{
if (is_leaf)
{
Expand Down
4 changes: 2 additions & 2 deletions src/details/ArborX_DetailsHappyTreeFriends.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,12 @@ struct HappyTreeFriends
#else
auto const &
#endif
getLeafBoundingVolume(BVH const &bvh, int i)
getIndexable(BVH const &bvh, int i)
{
static_assert(
std::is_same_v<decltype(bvh._internal_nodes(0).bounding_volume),
decltype(bvh._leaf_nodes(0).value.bounding_volume)>);
return bvh._leaf_nodes(i).value.bounding_volume;
return bvh._indexable_getter(getValue(bvh, i));
}

template <class BVH>
Expand Down
98 changes: 40 additions & 58 deletions src/details/ArborX_DetailsTreeConstruction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#ifndef ARBORX_DETAILS_TREE_CONSTRUCTION_HPP
#define ARBORX_DETAILS_TREE_CONSTRUCTION_HPP

#include <ArborX_AccessTraits.hpp>
#include <ArborX_DetailsAlgorithms.hpp> // expand
#include <ArborX_DetailsKokkosExtArithmeticTraits.hpp>
#include <ArborX_DetailsNode.hpp> // makeLeafNode
Expand All @@ -22,77 +21,59 @@

#include <cassert>

namespace ArborX
{
namespace Details
{
namespace TreeConstruction
namespace ArborX::Details::TreeConstruction
{

template <typename ExecutionSpace, typename Primitives, typename Box>
template <typename ExecutionSpace, typename Indexables, typename Box>
inline void calculateBoundingBoxOfTheScene(ExecutionSpace const &space,
Primitives const &primitives,
Indexables const &indexables,
Box &scene_bounding_box)
{
using Access = AccessTraits<Primitives, PrimitivesTag>;
auto const n = Access::size(primitives);
Kokkos::parallel_reduce(
"ArborX::TreeConstruction::calculate_bounding_box_of_the_scene",
Kokkos::RangePolicy<ExecutionSpace>(space, 0, n),
KOKKOS_LAMBDA(int i, Box &update) {
update += Access::get(primitives, i);
},
Kokkos::RangePolicy<ExecutionSpace>(space, 0, indexables.size()),
KOKKOS_LAMBDA(int i, Box &update) { update += indexables(i); },
Kokkos::Sum<Box>{scene_bounding_box});
}

template <typename ExecutionSpace, typename Primitives,
template <typename ExecutionSpace, typename Indexables,
typename SpaceFillingCurve, typename Box, typename LinearOrdering>
inline void projectOntoSpaceFillingCurve(ExecutionSpace const &space,
Primitives const &primitives,
Indexables const &indexables,
SpaceFillingCurve const &curve,
Box const &scene_bounding_box,
LinearOrdering linear_ordering_indices)
{
using Access = AccessTraits<Primitives, PrimitivesTag>;

size_t const n = Access::size(primitives);
size_t const n = indexables.size();
ARBORX_ASSERT(linear_ordering_indices.extent(0) == n);
static_assert(
std::is_same<typename LinearOrdering::value_type,
decltype(curve(scene_bounding_box,
Access::get(primitives, 0)))>::value);
decltype(curve(scene_bounding_box, indexables(0)))>::value);

Kokkos::parallel_for(
"ArborX::TreeConstruction::project_primitives_onto_space_filling_curve",
Kokkos::RangePolicy<ExecutionSpace>(space, 0, n), KOKKOS_LAMBDA(int i) {
linear_ordering_indices(i) =
curve(scene_bounding_box, Access::get(primitives, i));
linear_ordering_indices(i) = curve(scene_bounding_box, indexables(i));
});
}

template <typename ExecutionSpace, typename Primitives, typename Nodes>
template <typename ExecutionSpace, typename Values, typename Nodes>
inline void initializeSingleLeafNode(ExecutionSpace const &space,
Primitives const &primitives,
Values const &values,
Nodes const &leaf_nodes)
{
using Access = AccessTraits<Primitives, PrimitivesTag>;
using Value = typename Nodes::value_type::value_type;
using BoundingVolume = decltype(std::declval<Value>().bounding_volume);

ARBORX_ASSERT(leaf_nodes.extent(0) == 1);
ARBORX_ASSERT(Access::size(primitives) == 1);
ARBORX_ASSERT(values.size() == 1);

Kokkos::parallel_for(
"ArborX::TreeConstruction::initialize_single_leaf",
Kokkos::RangePolicy<ExecutionSpace>(space, 0, 1), KOKKOS_LAMBDA(int) {
BoundingVolume bounding_volume{};
expand(bounding_volume, Access::get(primitives, 0));
leaf_nodes(0) = makeLeafNode(Value{(unsigned)0, bounding_volume});
});
Kokkos::RangePolicy<ExecutionSpace>(space, 0, 1),
KOKKOS_LAMBDA(int) { leaf_nodes(0) = makeLeafNode(values(0)); });
}

template <typename Primitives, typename PermutationIndices,
typename LinearOrdering, typename LeafNodes, typename InternalNodes>
template <typename Values, typename IndexableGetter,
typename PermutationIndices, typename LinearOrdering,
typename LeafNodes, typename InternalNodes>
class GenerateHierarchy
{
static constexpr int UNTOUCHED_NODE = -1;
Expand All @@ -102,11 +83,13 @@ class GenerateHierarchy

public:
template <typename ExecutionSpace>
GenerateHierarchy(ExecutionSpace const &space, Primitives const &primitives,
GenerateHierarchy(ExecutionSpace const &space, Values const &values,
IndexableGetter const &indexable_getter,
PermutationIndices const &permutation_indices,
LinearOrdering const &sorted_morton_codes,
LeafNodes leaf_nodes, InternalNodes internal_nodes)
: _primitives(primitives)
: _values(values)
, _indexable_getter(indexable_getter)
, _permutation_indices(permutation_indices)
, _sorted_morton_codes(sorted_morton_codes)
, _leaf_nodes(leaf_nodes)
Expand Down Expand Up @@ -198,19 +181,17 @@ class GenerateHierarchy

KOKKOS_FUNCTION void operator()(int i) const
{
// Index in the original order primitives were given in.
// Index in the original order values were given in
auto const original_index = _permutation_indices(i);

// Initialize leaf node
auto &leaf_node = _leaf_nodes(i);
leaf_node = makeLeafNode(_values(original_index));

using BoundingVolume =
typename InternalNodes::value_type::bounding_volume_type;
BoundingVolume bounding_volume{};
using Access = AccessTraits<Primitives, PrimitivesTag>;
expand(bounding_volume, Access::get(_primitives, original_index));

// Initialize leaf node
using Value = typename LeafNodes::value_type::value_type;
auto &leaf_node = _leaf_nodes(i);
leaf_node = makeLeafNode(Value{original_index, bounding_volume});
expand(bounding_volume, _indexable_getter(leaf_node.value));

// For a leaf node, the range is just one index
int range_left = i;
Expand Down Expand Up @@ -271,7 +252,7 @@ class GenerateHierarchy
Kokkos::load_fence();
expand(bounding_volume,
right_child_is_leaf
? _leaf_nodes(right_child).value.bounding_volume
? _indexable_getter(_leaf_nodes(right_child).value)
: _internal_nodes(right_child).bounding_volume);
}
else
Expand All @@ -294,7 +275,7 @@ class GenerateHierarchy
Kokkos::load_fence();
expand(bounding_volume,
left_child_is_leaf
? _leaf_nodes(left_child).value.bounding_volume
? _indexable_getter(_leaf_nodes(left_child).value)
: _internal_nodes(left_child).bounding_volume);

if (!left_child_is_leaf)
Expand All @@ -315,7 +296,8 @@ class GenerateHierarchy
}

private:
Primitives _primitives;
Values _values;
IndexableGetter _indexable_getter;
PermutationIndices _permutation_indices;
LinearOrdering _sorted_morton_codes;
LeafNodes _leaf_nodes;
Expand All @@ -324,13 +306,14 @@ class GenerateHierarchy
int _num_internal_nodes;
};

template <typename ExecutionSpace, typename Primitives,
template <typename ExecutionSpace, typename Values, typename IndexableGetter,
typename... PermutationIndicesViewProperties,
typename LinearOrderingValueType,
typename... LinearOrderingViewProperties, typename LeafNodes,
typename InternalNodes>
void generateHierarchy(
ExecutionSpace const &space, Primitives const &primitives,
ExecutionSpace const &space, Values const &values,
IndexableGetter const &indexable_getter,
Kokkos::View<unsigned int *, PermutationIndicesViewProperties...>
permutation_indices,
Kokkos::View<LinearOrderingValueType *, LinearOrderingViewProperties...>
Expand All @@ -342,13 +325,12 @@ void generateHierarchy(
using ConstLinearOrdering = Kokkos::View<LinearOrderingValueType const *,
LinearOrderingViewProperties...>;

GenerateHierarchy(
space, primitives, ConstPermutationIndices(permutation_indices),
ConstLinearOrdering(sorted_morton_codes), leaf_nodes, internal_nodes);
GenerateHierarchy(space, values, indexable_getter,
ConstPermutationIndices(permutation_indices),
ConstLinearOrdering(sorted_morton_codes), leaf_nodes,
internal_nodes);
}

} // namespace TreeConstruction
} // namespace Details
} // namespace ArborX
} // namespace ArborX::Details::TreeConstruction

#endif
15 changes: 7 additions & 8 deletions src/details/ArborX_DetailsTreeTraversal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ struct TreeTraversal<BVH, Predicates, Callback, SpatialPredicateTag>
auto const &predicate = Access::get(_predicates, queryIndex);
auto const root = 0;
auto const &root_bounding_volume =
HappyTreeFriends::getLeafBoundingVolume(_bvh, root);
HappyTreeFriends::getIndexable(_bvh, root);
if (predicate(root_bounding_volume))
{
_callback(predicate, HappyTreeFriends::getValue(_bvh, 0));
Expand All @@ -94,10 +94,9 @@ struct TreeTraversal<BVH, Predicates, Callback, SpatialPredicateTag>
{
bool const is_leaf = HappyTreeFriends::isLeaf(_bvh, node);

if (predicate(
(is_leaf
? HappyTreeFriends::getLeafBoundingVolume(_bvh, node)
: HappyTreeFriends::getInternalBoundingVolume(_bvh, node))))
if (predicate((is_leaf ? HappyTreeFriends::getIndexable(_bvh, node)
: HappyTreeFriends::getInternalBoundingVolume(
_bvh, node))))
{
if (is_leaf)
{
Expand Down Expand Up @@ -263,7 +262,7 @@ struct TreeTraversal<BVH, Predicates, Callback, NearestPredicateTag>
auto const distance = [&predicate, &bvh](int j) {
return predicate.distance(
HappyTreeFriends::isLeaf(bvh, j)
? HappyTreeFriends::getLeafBoundingVolume(bvh, j)
? HappyTreeFriends::getIndexable(bvh, j)
: HappyTreeFriends::getInternalBoundingVolume(bvh, j));
};

Expand Down Expand Up @@ -431,7 +430,7 @@ struct TreeTraversal<BVH, Predicates, Callback,
auto const &predicate = Access::get(_predicates, queryIndex);
auto const root = 0;
auto const &root_bounding_volume =
HappyTreeFriends::getLeafBoundingVolume(_bvh, root);
HappyTreeFriends::getIndexable(_bvh, root);
using distance_type =
decltype(distance(getGeometry(predicate), root_bounding_volume));
constexpr auto inf =
Expand Down Expand Up @@ -472,7 +471,7 @@ struct TreeTraversal<BVH, Predicates, Callback,
auto const distance = [&predicate, &bvh](int j) {
return predicate.distance(
HappyTreeFriends::isLeaf(bvh, j)
? HappyTreeFriends::getLeafBoundingVolume(bvh, j)
? HappyTreeFriends::getIndexable(bvh, j)
: HappyTreeFriends::getInternalBoundingVolume(bvh, j));
};

Expand Down
Loading

0 comments on commit 14d0cf3

Please sign in to comment.