Skip to content

Commit

Permalink
feat: generic Grid iterator (#2718)
Browse files Browse the repository at this point in the history
Just an idea @andiwand @paulgessinger @LuisFelipeCoelho @noemina 

This adds two grid iterators:
- A global iterator that simply runs on the global index. As such you also run on the under/over flow bins
- A local iterator that uses instead local indexes. This one avoids under/over flow bins

The cool thing about the local one is that is also allows for a custom navigation pattern for any axis. This is currently done for the Z azis where we jump from the first bins, then the last bins and then the central Z bins in the grid

Still a draft since I need to add a few things. But opening anyway to get additional feedbacks
  • Loading branch information
CarloVarni authored Dec 15, 2023
1 parent 9fcbbe8 commit 664add3
Show file tree
Hide file tree
Showing 9 changed files with 1,155 additions and 85 deletions.
32 changes: 21 additions & 11 deletions Core/include/Acts/Seeding/BinnedSPGroup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Acts/Seeding/Seed.hpp"
#include "Acts/Seeding/SeedFinderConfig.hpp"
#include "Acts/Seeding/SpacePointGrid.hpp"
#include "Acts/Utilities/GridIterator.hpp"
#include "Acts/Utilities/Holders.hpp"

#include <memory>
Expand All @@ -39,9 +40,12 @@ class BinnedSPGroupIterator {
public:
// Never take ownerships
BinnedSPGroupIterator(BinnedSPGroup<external_spacepoint_t>&& group,
std::size_t) = delete;
std::array<std::size_t, 2> index,
std::array<std::vector<std::size_t>, 2> navigation) =
delete;
BinnedSPGroupIterator(BinnedSPGroup<external_spacepoint_t>& group,
std::size_t index);
std::array<std::size_t, 2> index,
std::array<std::vector<std::size_t>, 2> navigation);

BinnedSPGroupIterator(const BinnedSPGroupIterator&) = delete;
BinnedSPGroupIterator& operator=(const BinnedSPGroupIterator&) = delete;
Expand All @@ -66,10 +70,12 @@ class BinnedSPGroupIterator {
private:
// The group, it contains the grid and the bin finders
Acts::detail::RefHolder<BinnedSPGroup<external_spacepoint_t>> m_group;
// Max Local Bins - limits of the grid
std::array<std::size_t, 2> m_max_localBins;
// Current Local Bins
std::array<std::size_t, 2> m_current_localBins{0, 0};
// Current grid iterator
typename Acts::SpacePointGrid<external_spacepoint_t>::local_iterator_t
m_gridItr;
// End iterator
typename Acts::SpacePointGrid<external_spacepoint_t>::local_iterator_t
m_gridItrEnd;
};

/// @c BinnedSPGroup Provides access to begin and end BinnedSPGroupIterator
Expand All @@ -81,6 +87,8 @@ class BinnedSPGroup {
friend BinnedSPGroupIterator<external_spacepoint_t>;
#endif

enum INDEX : int { PHI = 0, Z = 1 };

public:
BinnedSPGroup() = delete;

Expand Down Expand Up @@ -119,17 +127,19 @@ class BinnedSPGroup {

private:
// grid with ownership of all InternalSpacePoint
std::unique_ptr<Acts::SpacePointGrid<external_spacepoint_t>> m_grid;
std::unique_ptr<Acts::SpacePointGrid<external_spacepoint_t>> m_grid{nullptr};

// BinFinder must return std::vector<Acts::Seeding::Bin> with content of
// each bin sorted in r (ascending)
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_topBinFinder;
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_bottomBinFinder;
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_topBinFinder{
nullptr};
std::shared_ptr<const BinFinder<external_spacepoint_t>> m_bottomBinFinder{
nullptr};

// Order of z bins to loop over when searching for SPs
std::vector<std::size_t> m_bins;
std::array<std::vector<std::size_t>, 2> m_bins{};
// Number of Z bins to skip the search for middle SP
std::size_t m_skipZMiddleBin;
std::size_t m_skipZMiddleBin{0ul};
};

} // namespace Acts
Expand Down
118 changes: 48 additions & 70 deletions Core/include/Acts/Seeding/BinnedSPGroup.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,31 @@

template <typename external_spacepoint_t>
Acts::BinnedSPGroupIterator<external_spacepoint_t>::BinnedSPGroupIterator(
Acts::BinnedSPGroup<external_spacepoint_t>& group, std::size_t index)
: m_group(group), m_max_localBins(m_group->m_grid->numLocalBins()) {
m_max_localBins[INDEX::PHI] += 1;
m_current_localBins[INDEX::Z] = m_group->skipZMiddleBin();
if (index == m_group->m_grid->size()) {
m_current_localBins = m_max_localBins;
} else {
// Go to the next not-empty bin
findNotEmptyBin();
}
Acts::BinnedSPGroup<external_spacepoint_t>& group,
std::array<std::size_t, 2> index,
std::array<std::vector<std::size_t>, 2> navigation)
: m_group(group), m_gridItr(*group.m_grid.get(), index, navigation) {
std::array<std::size_t, 2ul> endline{};
endline[0ul] = navigation[0ul].size();
endline[1ul] = navigation[1ul].size();
m_gridItrEnd =
typename Acts::SpacePointGrid<external_spacepoint_t>::local_iterator_t(
*group.m_grid.get(), endline, std::move(navigation));
findNotEmptyBin();
}

template <typename external_spacepoint_t>
inline Acts::BinnedSPGroupIterator<external_spacepoint_t>&
Acts::BinnedSPGroupIterator<external_spacepoint_t>::operator++() {
// Increase the position by one
// if we were on the edge, go up one phi bin and reset z bin
if (++m_current_localBins[INDEX::Z] == m_max_localBins[INDEX::Z]) {
++m_current_localBins[INDEX::PHI];
m_current_localBins[INDEX::Z] = m_group->skipZMiddleBin();
}

// Get the next not-empty bin in the grid
++m_gridItr;
findNotEmptyBin();
return *this;
}

template <typename external_spacepoint_t>
inline bool Acts::BinnedSPGroupIterator<external_spacepoint_t>::operator==(
const Acts::BinnedSPGroupIterator<external_spacepoint_t>& other) const {
return m_group.ptr == other.m_group.ptr &&
m_current_localBins[INDEX::PHI] ==
other.m_current_localBins[INDEX::PHI] &&
m_current_localBins[INDEX::Z] == other.m_current_localBins[INDEX::Z];
return m_group.ptr == other.m_group.ptr && m_gridItr == other.m_gridItr;
}

template <typename external_spacepoint_t>
Expand All @@ -59,20 +50,18 @@ std::tuple<boost::container::small_vector<std::size_t, 9>, std::size_t,
boost::container::small_vector<std::size_t, 9>>
Acts::BinnedSPGroupIterator<external_spacepoint_t>::operator*() const {
// Global Index
std::size_t global_index = m_group->m_grid->globalBinFromLocalBins(
{m_current_localBins[INDEX::PHI],
m_group->m_bins[m_current_localBins[INDEX::Z]]});
std::array<std::size_t, 2> localPosition = m_gridItr.localPosition();
std::size_t global_index =
m_group->m_grid->globalBinFromLocalBins(localPosition);

boost::container::small_vector<std::size_t, 9> bottoms =
m_group->m_bottomBinFinder->findBins(
m_current_localBins[INDEX::PHI],
m_group->m_bins[m_current_localBins[INDEX::Z]],
m_group->m_grid.get());
m_group->m_bottomBinFinder->findBins(localPosition[INDEX::PHI],
localPosition[INDEX::Z],
m_group->m_grid.get());
boost::container::small_vector<std::size_t, 9> tops =
m_group->m_topBinFinder->findBins(
m_current_localBins[INDEX::PHI],
m_group->m_bins[m_current_localBins[INDEX::Z]],
m_group->m_grid.get());
m_group->m_topBinFinder->findBins(localPosition[INDEX::PHI],
localPosition[INDEX::Z],
m_group->m_grid.get());

// GCC12+ in Release throws an overread warning here due to the move.
// This is from inside boost code, so best we can do is to suppress it.
Expand All @@ -89,37 +78,15 @@ Acts::BinnedSPGroupIterator<external_spacepoint_t>::operator*() const {
template <typename external_spacepoint_t>
inline void
Acts::BinnedSPGroupIterator<external_spacepoint_t>::findNotEmptyBin() {
if (m_gridItr == m_gridItrEnd) {
return;
}
// Iterate on the grid till we find a not-empty bin
// We start from the current bin configuration and move forward

for (std::size_t phiBin(m_current_localBins[INDEX::PHI]);
phiBin < m_max_localBins[INDEX::PHI]; ++phiBin) {
// 0 is the underflow - skip
if (phiBin == 0) {
continue;
}

for (std::size_t zBin(m_current_localBins[INDEX::Z]);
zBin < m_max_localBins[INDEX::Z]; ++zBin) {
std::size_t zBinIndex = m_group->m_bins[zBin];
std::size_t index =
m_group->m_grid->globalBinFromLocalBins({phiBin, zBinIndex});
// Check if there are entries in this bin
if (m_group->m_grid->at(index).empty()) {
continue;
}

// Set the new current bins
m_current_localBins[INDEX::PHI] = phiBin;
m_current_localBins[INDEX::Z] = zBin;
return;
}
// Reset z-index
m_current_localBins[INDEX::Z] = m_group->skipZMiddleBin();
std::size_t dimCollection = (*m_gridItr).size();
while (dimCollection == 0ul && ++m_gridItr != m_gridItrEnd) {
dimCollection = (*m_gridItr).size();
}

// Could find nothing ... setting this to end()
m_current_localBins = m_max_localBins;
}

// Binned SP Group
Expand Down Expand Up @@ -231,13 +198,21 @@ Acts::BinnedSPGroup<external_spacepoint_t>::BinnedSPGroup(
m_topBinFinder = tBinFinder;

m_skipZMiddleBin = config.skipZMiddleBinSearch;
m_bins = config.zBinsCustomLooping;
if (m_bins.empty()) {
std::size_t nZbins = m_grid->numLocalBins()[1];
m_bins.reserve(nZbins);
for (std::size_t i(0); i < nZbins; ++i) {
m_bins.push_back(i + 1);
}

// phi axis
m_bins[INDEX::PHI].resize(m_grid->numLocalBins()[0]);
std::iota(m_bins[INDEX::PHI].begin(), m_bins[INDEX::PHI].end(), 1ul);

// z axis
if (config.zBinsCustomLooping.empty()) {
std::size_t nZbins = m_grid->numLocalBins()[1] - m_skipZMiddleBin;
m_bins[INDEX::Z] = std::vector<std::size_t>(nZbins);
std::iota(m_bins[INDEX::Z].begin(), m_bins[INDEX::Z].end(),
1ul + m_skipZMiddleBin);
} else {
m_bins[INDEX::Z] = std::vector<std::size_t>(
config.zBinsCustomLooping.begin() + m_skipZMiddleBin,
config.zBinsCustomLooping.end());
}
}

Expand All @@ -249,11 +224,14 @@ inline std::size_t Acts::BinnedSPGroup<external_spacepoint_t>::size() const {
template <typename external_spacepoint_t>
inline Acts::BinnedSPGroupIterator<external_spacepoint_t>
Acts::BinnedSPGroup<external_spacepoint_t>::begin() {
return {*this, 0};
return {*this, {0ul, 0ul}, m_bins};
}

template <typename external_spacepoint_t>
inline Acts::BinnedSPGroupIterator<external_spacepoint_t>
Acts::BinnedSPGroup<external_spacepoint_t>::end() {
return {*this, m_grid->size()};
std::array<std::size_t, 2ul> endline{};
endline[0ul] = m_bins[0ul].size();
endline[1ul] = m_bins[1ul].size();
return {*this, endline, m_bins};
}
31 changes: 31 additions & 0 deletions Core/include/Acts/Utilities/Grid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
#include <type_traits>
#include <vector>

namespace Acts {
template <typename T, class... Axes>
class GridGlobalIterator;

template <typename T, class... Axes>
class GridLocalIterator;
} // namespace Acts

namespace Acts {

/// @brief class for describing a regular multi-dimensional grid
Expand Down Expand Up @@ -48,6 +56,10 @@ class Grid final {
using point_t = std::array<ActsScalar, DIM>;
/// index type using local bin indices along each axis
using index_t = std::array<std::size_t, DIM>;
/// global iterator type
using global_iterator_t = Acts::GridGlobalIterator<T, Axes...>;
/// local iterator type
using local_iterator_t = Acts::GridLocalIterator<T, Axes...>;

/// @brief default constructor
///
Expand Down Expand Up @@ -457,6 +469,25 @@ class Grid final {
return detail::grid_helper::getAxes(m_axes);
}

global_iterator_t begin() const { return global_iterator_t(*this, 0); }

global_iterator_t end() const { return global_iterator_t(*this, size()); }

local_iterator_t begin(
const std::array<std::vector<std::size_t>, DIM>& navigator) const {
std::array<std::size_t, DIM> localBin{};
return local_iterator_t(*this, std::move(localBin), navigator);
}

local_iterator_t end(
const std::array<std::vector<std::size_t>, DIM>& navigator) const {
std::array<std::size_t, DIM> endline{};
for (std::size_t i(0ul); i < DIM; ++i) {
endline[i] = navigator[i].size();
}
return local_iterator_t(*this, std::move(endline), navigator);
}

private:
/// set of axis defining the multi-dimensional grid
std::tuple<Axes...> m_axes;
Expand Down
Loading

0 comments on commit 664add3

Please sign in to comment.