Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get column value by column label in Framework Core ASoA #13498

Open
wants to merge 30 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0848246
use generic get() in row_helpers
mytkom Sep 8, 2024
859d53f
backward compatibility for binning policy
mytkom Sep 9, 2024
b46bb30
getColumnValueByLabel function
mytkom Sep 9, 2024
eb14b82
reverse logic
mytkom Sep 9, 2024
fa017a8
benchmark for getColumnValueByLabel
mytkom Sep 10, 2024
351e4c8
formatting adjustments
mytkom Sep 10, 2024
4de9d59
getColumnGetterByLabel and benchmarks
mytkom Sep 12, 2024
0f0767c
formatting adjustments
mytkom Sep 12, 2024
da16b87
improve performance by not using std::function
mytkom Sep 26, 2024
27ed43c
Please consider the following formatting changes
alibuild Sep 26, 2024
47330d5
Merge pull request #2 from alibuild/alibot-cleanup-13498
mytkom Sep 26, 2024
48f0f2c
remove event mixing changes from this branch
mytkom Sep 30, 2024
a34dde4
add forgotten functions
mytkom Oct 1, 2024
bbbf43e
fix column name condition for dynamic columns
mytkom Oct 8, 2024
12b90e0
style improvements + using concepts for conditional code and selectin…
mytkom Oct 13, 2024
56b5790
Please consider the following formatting changes
alibuild Oct 13, 2024
385cf7d
Merge pull request #3 from alibuild/alibot-cleanup-13498
mytkom Oct 13, 2024
03dd07a
remove bindings_types_t
mytkom Oct 14, 2024
bd1ebfa
use strncmp and use nullptr as fallback
mytkom Oct 14, 2024
2c918a8
Please consider the following formatting changes
alibuild Oct 14, 2024
123a6d8
Merge pull request #4 from alibuild/alibot-cleanup-13498
mytkom Oct 14, 2024
399df03
use strcmp
mytkom Oct 14, 2024
3ed7509
fix dynamic column logic
mytkom Oct 15, 2024
8651255
Please consider the following formatting changes
alibuild Oct 15, 2024
6e55f8d
Merge pull request #5 from alibuild/alibot-cleanup-13498
mytkom Oct 15, 2024
8a1cc25
refactor string comparison
mytkom Nov 14, 2024
84510eb
fix edge case
mytkom Nov 14, 2024
1546f60
use early return
mytkom Nov 15, 2024
9c4df8e
formatting
mytkom Nov 15, 2024
962a8d2
use temporary string_view and starts_with method
mytkom Nov 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions Framework/Core/include/Framework/ASoA.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <gandiva/selection_vector.h>
#include <cassert>
#include <fmt/format.h>
#include <concepts>
#include <gsl/span>
#include <limits>

Expand Down Expand Up @@ -1988,6 +1989,74 @@ std::tuple<typename Cs::type...> getRowData(arrow::Table* table, T rowIterator,
{
return std::make_tuple(getSingleRowData<T, Cs>(table, rowIterator, ci, ai, globalIndex)...);
}

template <typename R, typename T, typename C>
R getColumnValue(const T& rowIterator)
{
return static_cast<R>(static_cast<C>(rowIterator).get());
ktf marked this conversation as resolved.
Show resolved Hide resolved
}

template <typename R, typename T>
using ColumnGetterFunction = R (*)(const T&);

template <typename T, typename R>
concept dynamic_with_common_getter = is_dynamic_v<T> &&
// lambda is callable without additional free args
framework::pack_size(typename T::bindings_t{}) == framework::pack_size(typename T::callable_t::args{}) &&
requires(T t) {
{ t.get() } -> std::convertible_to<R>;
};

template <typename T, typename R>
concept persistent_with_common_getter = is_persistent_v<T> && requires(T t) {
{ t.get() } -> std::convertible_to<R>;
};

template <typename T, typename R>
using with_common_getter_t = typename std::conditional<persistent_with_common_getter<T, R> || dynamic_with_common_getter<T, R>, std::true_type, std::false_type>::type;
mytkom marked this conversation as resolved.
Show resolved Hide resolved

template <typename R, typename T, persistent_with_common_getter<R> C>
ColumnGetterFunction<R, T> createGetterPtr(const std::string_view& columnLabel, bool& found)
{
if (std::strcmp(columnLabel.data(), C::columnLabel()) == 0) {
found = true;
}

return &getColumnValue<R, T, C>;
mytkom marked this conversation as resolved.
Show resolved Hide resolved
}

template <typename R, typename T, dynamic_with_common_getter<R> C>
ColumnGetterFunction<R, T> createGetterPtr(const std::string_view& columnLabel, bool& found)
{
if (std::strcmp(&columnLabel[1], C::columnLabel()) == 0 || std::strcmp(columnLabel.data(), C::columnLabel()) == 0) {
mytkom marked this conversation as resolved.
Show resolved Hide resolved
found = true;
}

return &getColumnValue<R, T, C>;
}

template <typename R, typename T, typename... Cs>
ColumnGetterFunction<R, T> getColumnGetterByLabel(o2::framework::pack<Cs...>, const std::string_view& columnLabel)
{
bool found = false;
ColumnGetterFunction<R, T> func;

(void)((func = createGetterPtr<R, T, Cs>(columnLabel, found), found) || ...);

if (!found) {
throw std::runtime_error("Getter for provided columnLabel not found!");
mytkom marked this conversation as resolved.
Show resolved Hide resolved
}

return func;
}

template <typename R, typename T>
ColumnGetterFunction<R, typename T::iterator> getColumnGetterByLabel(const std::string_view& columnLabel)
{
using TypesWithCommonGetter = o2::framework::selected_pack_multicondition<with_common_getter_t, framework::pack<R>, typename T::columns>;

return getColumnGetterByLabel<R, typename T::iterator>(TypesWithCommonGetter{}, columnLabel);
}
} // namespace row_helpers
} // namespace o2::soa

Expand Down Expand Up @@ -2730,6 +2799,7 @@ DECLARE_SOA_ITERATOR_METADATA();
} \
\
using bindings_t = typename o2::framework::pack<Bindings...>; \
using bindings_types_t = typename o2::framework::pack<typename Bindings::type...>; \
mytkom marked this conversation as resolved.
Show resolved Hide resolved
std::tuple<o2::soa::ColumnIterator<typename Bindings::type> const*...> boundIterators; \
}

Expand Down
60 changes: 60 additions & 0 deletions Framework/Core/test/benchmark_ASoA.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ DECLARE_SOA_COLUMN_FULL(X, x, float, "x");
DECLARE_SOA_COLUMN_FULL(Y, y, float, "y");
DECLARE_SOA_COLUMN_FULL(Z, z, float, "z");
DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](float x, float y) { return x + y; });
DECLARE_SOA_DYNAMIC_COLUMN(SumFreeArgs, sumFreeArgs, [](float x, float y, float freeArg) { return x + y + freeArg; });
} // namespace test

DECLARE_SOA_TABLE(TestTable, "AOD", "TESTTBL", test::X, test::Y, test::Z, test::Sum<test::X, test::Y>);
Expand Down Expand Up @@ -288,6 +289,36 @@ static void BM_ASoADynamicColumnPresent(benchmark::State& state)

BENCHMARK(BM_ASoADynamicColumnPresent)->Range(8, 8 << maxrange);

static void BM_ASoADynamicColumnPresentGetGetterByLabel(benchmark::State& state)
{
// Seed with a real random value, if available
std::default_random_engine e1(1234567891);
std::uniform_real_distribution<float> uniform_dist(0, 1);

TableBuilder builder;
auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
for (auto i = 0; i < state.range(0); ++i) {
rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
}
auto table = builder.finalize();

using Test = o2::soa::Table<o2::framework::OriginEnc{"AOD"}, test::X, test::Y, test::Z, test::Sum<test::X, test::Y>>;

for (auto _ : state) {
Test tests{table};
float sum = 0;
auto xGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("x");
auto yGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("y");
for (auto& test : tests) {
sum += xGetter(test) + yGetter(test);
}
benchmark::DoNotOptimize(sum);
}
state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
}

BENCHMARK(BM_ASoADynamicColumnPresentGetGetterByLabel)->Range(8, 8 << maxrange);

static void BM_ASoADynamicColumnCall(benchmark::State& state)
{
// Seed with a real random value, if available
Expand Down Expand Up @@ -315,4 +346,33 @@ static void BM_ASoADynamicColumnCall(benchmark::State& state)
}
BENCHMARK(BM_ASoADynamicColumnCall)->Range(8, 8 << maxrange);

static void BM_ASoADynamicColumnCallGetGetterByLabel(benchmark::State& state)
{
// Seed with a real random value, if available
std::default_random_engine e1(1234567891);
std::uniform_real_distribution<float> uniform_dist(0, 1);

TableBuilder builder;
auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
for (auto i = 0; i < state.range(0); ++i) {
rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
}
auto table = builder.finalize();

// SumFreeArgs presence checks if dynamic columns get() is handled correctly during compilation
using Test = o2::soa::Table<o2::framework::OriginEnc{"AOD"}, test::X, test::Y, test::Sum<test::X, test::Y>, test::SumFreeArgs<test::X, test::Y>>;

Test tests{table};
for (auto _ : state) {
float sum = 0;
auto sumGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("Sum");
for (auto& test : tests) {
sum += sumGetter(test);
}
benchmark::DoNotOptimize(sum);
}
state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
}
BENCHMARK(BM_ASoADynamicColumnCallGetGetterByLabel)->Range(8, 8 << maxrange);

BENCHMARK_MAIN();
Loading