blob: 01d9ec944ee44022147623b4870fdb8d11c326aa [file] [log] [blame]
// 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 "benchmark/benchmark.h"
#include <vector>
#include "arrow/compute/api_scalar.h"
#include "arrow/compute/kernels/test_util.h"
#include "arrow/testing/gtest_util.h"
#include "arrow/testing/random.h"
#include "arrow/util/benchmark_util.h"
namespace arrow {
namespace compute {
constexpr auto kSeed = 0x94378165;
using BinaryOp = Result<Datum>(const Datum&, const Datum&, ArithmeticOptions,
ExecContext*);
// Add explicit overflow-checked shortcuts, for easy benchmark parametering.
static Result<Datum> AddChecked(const Datum& left, const Datum& right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR) {
options.check_overflow = true;
return Add(left, right, std::move(options), ctx);
}
static Result<Datum> SubtractChecked(const Datum& left, const Datum& right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR) {
options.check_overflow = true;
return Subtract(left, right, std::move(options), ctx);
}
static Result<Datum> MultiplyChecked(const Datum& left, const Datum& right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR) {
options.check_overflow = true;
return Multiply(left, right, std::move(options), ctx);
}
static Result<Datum> DivideChecked(const Datum& left, const Datum& right,
ArithmeticOptions options = ArithmeticOptions(),
ExecContext* ctx = NULLPTR) {
options.check_overflow = true;
return Divide(left, right, std::move(options), ctx);
}
template <BinaryOp& Op, typename ArrowType, typename CType = typename ArrowType::c_type>
static void ArrayScalarKernel(benchmark::State& state) {
RegressionArgs args(state);
const int64_t array_size = args.size / sizeof(CType);
// Choose values so as to avoid overflow on all ops and types
auto min = static_cast<CType>(6);
auto max = static_cast<CType>(min + 15);
Datum rhs(static_cast<CType>(6));
auto rand = random::RandomArrayGenerator(kSeed);
auto lhs = std::static_pointer_cast<NumericArray<ArrowType>>(
rand.Numeric<ArrowType>(array_size, min, max, args.null_proportion));
for (auto _ : state) {
ABORT_NOT_OK(Op(lhs, rhs, ArithmeticOptions(), nullptr).status());
}
state.SetItemsProcessed(state.iterations() * array_size);
}
template <BinaryOp& Op, typename ArrowType, typename CType = typename ArrowType::c_type>
static void ArrayArrayKernel(benchmark::State& state) {
RegressionArgs args(state);
// Choose values so as to avoid overflow on all ops and types
const int64_t array_size = args.size / sizeof(CType);
auto rmin = static_cast<CType>(1);
auto rmax = static_cast<CType>(rmin + 6); // 7
auto lmin = static_cast<CType>(rmax + 1); // 8
auto lmax = static_cast<CType>(lmin + 6); // 14
auto rand = random::RandomArrayGenerator(kSeed);
auto lhs = std::static_pointer_cast<NumericArray<ArrowType>>(
rand.Numeric<ArrowType>(array_size, lmin, lmax, args.null_proportion));
auto rhs = std::static_pointer_cast<NumericArray<ArrowType>>(
rand.Numeric<ArrowType>(array_size, rmin, rmax, args.null_proportion));
for (auto _ : state) {
ABORT_NOT_OK(Op(lhs, rhs, ArithmeticOptions(), nullptr).status());
}
state.SetItemsProcessed(state.iterations() * array_size);
}
void SetArgs(benchmark::internal::Benchmark* bench) {
for (const auto inverse_null_proportion : std::vector<ArgsType>({100, 0})) {
bench->Args({static_cast<ArgsType>(kL2Size), inverse_null_proportion});
}
}
#define DECLARE_ARITHMETIC_BENCHMARKS(BENCHMARK, OP) \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int64Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int32Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int16Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int8Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt64Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt32Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt16Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt8Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, FloatType)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, DoubleType)->Apply(SetArgs)
// Checked floating-point variants of arithmetic operations are identical to
// non-checked variants, so do not bother measuring them.
#define DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(BENCHMARK, OP) \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int64Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int32Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int16Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, Int8Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt64Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt32Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt16Type)->Apply(SetArgs); \
BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt8Type)->Apply(SetArgs);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Add);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Add);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Subtract);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Subtract);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Multiply);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Multiply);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Divide);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Divide);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, AddChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, AddChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, SubtractChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, SubtractChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, MultiplyChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, MultiplyChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, DivideChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, DivideChecked);
} // namespace compute
} // namespace arrow