From 16f7cd517219aed427c352590aff48033a83ad62 Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 7 Jan 2025 11:34:20 +0100 Subject: [PATCH 1/4] Split prepareArgument() --- .../Core/include/Framework/GroupSlicer.h | 156 ++++++++++-------- 1 file changed, 90 insertions(+), 66 deletions(-) diff --git a/Framework/Core/include/Framework/GroupSlicer.h b/Framework/Core/include/Framework/GroupSlicer.h index 8fd96fb00156c..2f51d2f51ea17 100644 --- a/Framework/Core/include/Framework/GroupSlicer.h +++ b/Framework/Core/include/Framework/GroupSlicer.h @@ -22,7 +22,6 @@ namespace o2::framework { - template struct GroupSlicer { using grouping_t = std::decay_t; @@ -151,83 +150,108 @@ struct GroupSlicer { return std::make_tuple(prepareArgument()...); } - template + template + requires (o2::soa::relatedByIndex, std::decay_t>() && soa::is_filtered_table>) auto prepareArgument() { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); auto& originalTable = std::get(*mAt); - - if constexpr (o2::soa::relatedByIndex, std::decay_t>()) { - uint64_t pos; - if constexpr (soa::is_filtered_table>) { - pos = groupSelection[position]; - } else { - pos = position; + uint64_t pos; + if constexpr (soa::is_filtered_table>) { + pos = groupSelection[position]; + } else { + pos = position; + } + // generic split + auto selection = sliceInfosUnsorted[index].getSliceFor(pos); + // intersect selections + o2::soa::SelectionVector s; + if (selections[index]->empty()) { + if (!selection.empty()) { + std::copy(selection.begin(), selection.end(), std::back_inserter(s)); } - - if constexpr (!o2::soa::is_smallgroups>) { - // optimized split - if (originalTable.size() == 0) { - return originalTable; + } else { + if (!selection.empty()) { + if constexpr (std::decay_t::applyFilters) { + std::set_intersection(selection.begin(), selection.end(), selections[index]->begin(), selections[index]->end(), std::back_inserter(s)); + } else { + std::copy(selection.begin(), selection.end(), std::back_inserter(s)); } - auto oc = sliceInfos[index].getSliceFor(pos); - uint64_t offset = oc.first; - auto count = oc.second; - if constexpr (soa::is_filtered_table>) { - auto groupedElementsTable = originalTable.asArrowTable()->Slice(offset, count); - if (count == 0) { - return std::decay_t{{groupedElementsTable}, soa::SelectionVector{}}; - } + } + } + std::decay_t typedTable{{originalTable.asArrowTable()}, std::move(s)}; + typedTable.bindInternalIndicesTo(&originalTable); + return typedTable; + } + + template + requires (o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) + auto prepareArgument() + { + constexpr auto index = framework::has_type_at_v(associated_pack_t{}); + auto& originalTable = std::get(*mAt); + uint64_t pos; + if constexpr (soa::is_filtered_table>) { + pos = groupSelection[position]; + } else { + pos = position; + } + // optimized split + if (originalTable.size() == 0) { + return originalTable; + } + auto oc = sliceInfos[index].getSliceFor(pos); + uint64_t offset = oc.first; + auto count = oc.second; + auto groupedElementsTable = originalTable.asArrowTable()->Slice(offset, count); + if (count == 0) { + return std::decay_t{{groupedElementsTable}, soa::SelectionVector{}}; + } - // for each grouping element we need to slice the selection vector - auto start_iterator = std::lower_bound(starts[index], selections[index]->end(), offset); - auto stop_iterator = std::lower_bound(start_iterator, selections[index]->end(), offset + count); - starts[index] = stop_iterator; - soa::SelectionVector slicedSelection{start_iterator, stop_iterator}; - std::transform(slicedSelection.begin(), slicedSelection.end(), slicedSelection.begin(), - [&offset](int64_t idx) { - return idx - static_cast(offset); - }); + // for each grouping element we need to slice the selection vector + auto start_iterator = std::lower_bound(starts[index], selections[index]->end(), offset); + auto stop_iterator = std::lower_bound(start_iterator, selections[index]->end(), offset + count); + starts[index] = stop_iterator; + soa::SelectionVector slicedSelection{start_iterator, stop_iterator}; + std::transform(slicedSelection.begin(), slicedSelection.end(), slicedSelection.begin(), + [&offset](int64_t idx) { + return idx - static_cast(offset); + }); - std::decay_t typedTable{{groupedElementsTable}, std::move(slicedSelection), offset}; - typedTable.bindInternalIndicesTo(&originalTable); - return typedTable; + std::decay_t typedTable{{groupedElementsTable}, std::move(slicedSelection), offset}; + typedTable.bindInternalIndicesTo(&originalTable); + return typedTable; + } - } else { - auto groupedElementsTable = originalTable.rawSlice(offset, offset + count - 1); - groupedElementsTable.bindInternalIndicesTo(&originalTable); - return groupedElementsTable; - } - } else { - // generic split - if constexpr (soa::is_filtered_table>) { - auto selection = sliceInfosUnsorted[index].getSliceFor(pos); - // intersect selections - o2::soa::SelectionVector s; - if (selections[index]->empty()) { - if (!selection.empty()) { - std::copy(selection.begin(), selection.end(), std::back_inserter(s)); - } - } else { - if (!selection.empty()) { - if constexpr (std::decay_t::applyFilters) { - std::set_intersection(selection.begin(), selection.end(), selections[index]->begin(), selections[index]->end(), std::back_inserter(s)); - } else { - std::copy(selection.begin(), selection.end(), std::back_inserter(s)); - } - } - } - std::decay_t typedTable{{originalTable.asArrowTable()}, std::move(s)}; - typedTable.bindInternalIndicesTo(&originalTable); - return typedTable; - } else { - throw runtime_error("Unsorted grouped table needs to be used with soa::SmallGroups<>"); - } - } + template + requires (o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups && !soa::is_filtered_table) + auto prepareArgument() + { + constexpr auto index = framework::has_type_at_v(associated_pack_t{}); + auto& originalTable = std::get(*mAt); + uint64_t pos; + if constexpr (soa::is_filtered_table>) { + pos = groupSelection[position]; } else { - static_assert(!o2::soa::is_smallgroups>, "SmallGroups used with a table that is not related by index to the gouping table"); + pos = position; + } + // optimized split + if (originalTable.size() == 0) { return originalTable; } + auto oc = sliceInfos[index].getSliceFor(pos); + uint64_t offset = oc.first; + auto count = oc.second; + auto groupedElementsTable = originalTable.rawSlice(offset, offset + count - 1); + groupedElementsTable.bindInternalIndicesTo(&originalTable); + return groupedElementsTable; + } + + template + requires (!o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) + auto prepareArgument() + { + return std::get(*mAt); } std::string mIndexColumnName; From 11cf19dfadd8dccfdf277809d2f5f51d8fe6247b Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 7 Jan 2025 13:23:09 +0100 Subject: [PATCH 2/4] split splitting and extracting functions --- .../Core/include/Framework/GroupSlicer.h | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/Framework/Core/include/Framework/GroupSlicer.h b/Framework/Core/include/Framework/GroupSlicer.h index 2f51d2f51ea17..6620987c72f25 100644 --- a/Framework/Core/include/Framework/GroupSlicer.h +++ b/Framework/Core/include/Framework/GroupSlicer.h @@ -45,34 +45,42 @@ struct GroupSlicer { GroupSlicerIterator& operator=(GroupSlicerIterator&&) = default; template + auto splittingFunction(T&&) + { + } + + template + requires (o2::soa::relatedByIndex, std::decay_t>()) auto splittingFunction(T&& table) { constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); - if constexpr (o2::soa::relatedByIndex, std::decay_t>()) { - auto binding = o2::soa::getLabelFromTypeForKey>(mIndexColumnName); - auto bk = std::make_pair(binding, mIndexColumnName); - if constexpr (!o2::soa::is_smallgroups>) { - if (table.size() == 0) { - return; - } - sliceInfos[index] = mSlices->getCacheFor(bk); - } else { - if (table.tableSize() == 0) { - return; - } - sliceInfosUnsorted[index] = mSlices->getCacheUnsortedFor(bk); + auto binding = o2::soa::getLabelFromTypeForKey>(mIndexColumnName); + auto bk = std::make_pair(binding, mIndexColumnName); + if constexpr (!o2::soa::is_smallgroups>) { + if (table.size() == 0) { + return; } - } + sliceInfos[index] = mSlices->getCacheFor(bk); + } else { + if (table.tableSize() == 0) { + return; + } + sliceInfosUnsorted[index] = mSlices->getCacheUnsortedFor(bk); + } + } + + template + auto extractingFunction(T&&) + { } template + requires (soa::is_filtered_table>) auto extractingFunction(T&& table) { - if constexpr (soa::is_filtered_table>) { - constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); - selections[index] = &table.getSelectedRows(); - starts[index] = selections[index]->begin(); - } + constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); + selections[index] = &table.getSelectedRows(); + starts[index] = selections[index]->begin(); } GroupSlicerIterator(G& gt, std::tuple& at, ArrowTableSlicingCache& slices) @@ -190,6 +198,9 @@ struct GroupSlicer { { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); auto& originalTable = std::get(*mAt); + if (originalTable.size() == 0) { + return originalTable; + } uint64_t pos; if constexpr (soa::is_filtered_table>) { pos = groupSelection[position]; @@ -197,9 +208,6 @@ struct GroupSlicer { pos = position; } // optimized split - if (originalTable.size() == 0) { - return originalTable; - } auto oc = sliceInfos[index].getSliceFor(pos); uint64_t offset = oc.first; auto count = oc.second; @@ -229,6 +237,9 @@ struct GroupSlicer { { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); auto& originalTable = std::get(*mAt); + if (originalTable.size() == 0) { + return originalTable; + } uint64_t pos; if constexpr (soa::is_filtered_table>) { pos = groupSelection[position]; @@ -236,9 +247,6 @@ struct GroupSlicer { pos = position; } // optimized split - if (originalTable.size() == 0) { - return originalTable; - } auto oc = sliceInfos[index].getSliceFor(pos); uint64_t offset = oc.first; auto count = oc.second; From 703773dd6abb12d17f83a544d4a3492dd52802da Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 21 Jan 2025 12:44:05 +0100 Subject: [PATCH 3/4] fixup! split splitting and extracting functions --- Framework/Core/include/Framework/GroupSlicer.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Framework/Core/include/Framework/GroupSlicer.h b/Framework/Core/include/Framework/GroupSlicer.h index 6620987c72f25..5dcfda3853baf 100644 --- a/Framework/Core/include/Framework/GroupSlicer.h +++ b/Framework/Core/include/Framework/GroupSlicer.h @@ -74,8 +74,7 @@ struct GroupSlicer { { } - template - requires (soa::is_filtered_table>) + template auto extractingFunction(T&& table) { constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); @@ -159,7 +158,7 @@ struct GroupSlicer { } template - requires (o2::soa::relatedByIndex, std::decay_t>() && soa::is_filtered_table>) + requires (o2::soa::relatedByIndex, std::decay_t>() && soa::is_filtered_table) auto prepareArgument() { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); From 1e2b5b1558c9167bd8f02917c233bf6d63043bbc Mon Sep 17 00:00:00 2001 From: Anton Alkin Date: Tue, 21 Jan 2025 12:47:22 +0100 Subject: [PATCH 4/4] fixup! split splitting and extracting functions --- Framework/Core/include/Framework/GroupSlicer.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Framework/Core/include/Framework/GroupSlicer.h b/Framework/Core/include/Framework/GroupSlicer.h index 5dcfda3853baf..64b1d863c59e6 100644 --- a/Framework/Core/include/Framework/GroupSlicer.h +++ b/Framework/Core/include/Framework/GroupSlicer.h @@ -50,7 +50,7 @@ struct GroupSlicer { } template - requires (o2::soa::relatedByIndex, std::decay_t>()) + requires(o2::soa::relatedByIndex, std::decay_t>()) auto splittingFunction(T&& table) { constexpr auto index = framework::has_type_at_v>(associated_pack_t{}); @@ -66,7 +66,7 @@ struct GroupSlicer { return; } sliceInfosUnsorted[index] = mSlices->getCacheUnsortedFor(bk); - } + } } template @@ -158,7 +158,7 @@ struct GroupSlicer { } template - requires (o2::soa::relatedByIndex, std::decay_t>() && soa::is_filtered_table) + requires(o2::soa::relatedByIndex, std::decay_t>() && soa::is_filtered_table) auto prepareArgument() { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); @@ -191,8 +191,8 @@ struct GroupSlicer { return typedTable; } - template - requires (o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) + template + requires(o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) auto prepareArgument() { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); @@ -231,7 +231,7 @@ struct GroupSlicer { } template - requires (o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups && !soa::is_filtered_table) + requires(o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups && !soa::is_filtered_table) auto prepareArgument() { constexpr auto index = framework::has_type_at_v(associated_pack_t{}); @@ -255,7 +255,7 @@ struct GroupSlicer { } template - requires (!o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) + requires(!o2::soa::relatedByIndex, std::decay_t>() && !soa::is_smallgroups) auto prepareArgument() { return std::get(*mAt);