From 4de13028c149e3b9b5daf30cb414cf9bacc9d6dd Mon Sep 17 00:00:00 2001 From: Dewey Dunnington Date: Thu, 25 Apr 2024 10:19:03 -0300 Subject: [PATCH] benchmarks with zip/viewarrayas --- dev/benchmarks/CMakeLists.txt | 2 +- dev/benchmarks/c/array_benchmark.cc | 38 ++++++++++++ dev/benchmarks/c/util.h | 91 +++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 dev/benchmarks/c/util.h diff --git a/dev/benchmarks/CMakeLists.txt b/dev/benchmarks/CMakeLists.txt index bb452c176..e05bc32fb 100644 --- a/dev/benchmarks/CMakeLists.txt +++ b/dev/benchmarks/CMakeLists.txt @@ -27,7 +27,7 @@ if(NOT DEFINED CMAKE_C_STANDARD) endif() if(NOT DEFINED CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 11) + set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() diff --git a/dev/benchmarks/c/array_benchmark.cc b/dev/benchmarks/c/array_benchmark.cc index 9e028fcb2..37dae84d7 100644 --- a/dev/benchmarks/c/array_benchmark.cc +++ b/dev/benchmarks/c/array_benchmark.cc @@ -19,6 +19,12 @@ #include +#if NANOARROW_VERSION_MINOR >= 5 +#include "util.h" +using nanoarrow::Enumerate; +using nanoarrow::Zip; +#endif + // The length of most arrays used in these benchmarks. Just big enough so // that the benchmark takes a non-trivial amount of time to run. static const int64_t kNumItemsPrettyBig = 1000000; @@ -92,6 +98,37 @@ ArrowErrorCode InitArrayViewFromBuffers(ArrowType type, ArrowArray* array, return NANOARROW_OK; } +#if NANOARROW_VERSION_MINOR >= 5 + +template +static void BaseArrayViewGetInt(benchmark::State& state) { + nanoarrow::UniqueArray array; + nanoarrow::UniqueArrayView array_view; + + int64_t n_values = kNumItemsPrettyBig; + + std::vector values(n_values); + for (auto [i, value] : Zip(Enumerate, values)) { + value = i % std::numeric_limits::max(); + } + + NANOARROW_THROW_NOT_OK( + InitArrayViewFromBuffers(type, array.get(), array_view.get(), {}, values)); + + std::vector values_out(n_values); + for (auto _ : state) { + for (auto [i, array_slot, value_out] : + Zip(Enumerate, nanoarrow::ViewArrayAs(array_view.get()), values_out)) { + value_out = *array_slot; + } + benchmark::DoNotOptimize(values_out); + } + + state.SetItemsProcessed(n_values * state.iterations()); +} + +#else + template static void BaseArrayViewGetInt(benchmark::State& state) { nanoarrow::UniqueArray array; @@ -117,6 +154,7 @@ static void BaseArrayViewGetInt(benchmark::State& state) { state.SetItemsProcessed(n_values * state.iterations()); } +#endif /// \brief Use ArrowArrayViewGet() to consume an int8 array static void BenchmarkArrayViewGetInt8(benchmark::State& state) { diff --git a/dev/benchmarks/c/util.h b/dev/benchmarks/c/util.h new file mode 100644 index 000000000..0784893df --- /dev/null +++ b/dev/benchmarks/c/util.h @@ -0,0 +1,91 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +#include + +#include + +#if !defined(__cpp_variadic_using) || !defined(__cpp_deduction_guides) || \ + !defined(__cpp_fold_expressions) || !defined(__cpp_lib_integer_sequence) || \ + __cpp_range_based_for < 201603L // end sentinels +#error "Zip cannot be supported without C++17 features" +#endif + +namespace nanoarrow { + +template +struct Zip; + +template +Zip(Ranges&&...) -> Zip, std::index_sequence_for>; + +template +struct Zip, std::index_sequence> { + explicit Zip(Ranges... ranges) : ranges_(std::forward(ranges)...) {} + + std::tuple ranges_; + + using sentinel = std::tuple(ranges_).end())...>; + + struct iterator : std::tuple(ranges_).begin())...> { + using iterator::tuple::tuple; + + auto operator*() { + return std::tuple(*this))...>{*std::get(*this)...}; + } + + iterator& operator++() { + (++std::get(*this), ...); + return *this; + } + + bool operator!=(const sentinel& s) const { + bool any_iterator_at_end = (... || (std::get(*this) == std::get(s))); + return !any_iterator_at_end; + } + }; + + iterator begin() { return {std::get(ranges_).begin()...}; } + + sentinel end() { return {std::get(ranges_).end()...}; } +}; + +constexpr auto Enumerate = [] { + struct { + struct sentinel {}; + constexpr sentinel end() const { return {}; } + + struct iterator { + int64_t i{0}; + + constexpr int64_t operator*() { return i; } + + constexpr iterator& operator++() { + ++i; + return *this; + } + + constexpr std::true_type operator!=(sentinel) const { return {}; } + constexpr std::false_type operator==(sentinel) const { return {}; } + }; + constexpr iterator begin() const { return {}; } + } out; + + return out; +}(); + +} // namespace nanoarrow