From 8d2e9b51703730043b13445c1c975f8c7ea4b96a Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Mon, 6 May 2019 15:57:21 +0200 Subject: [PATCH 1/2] Extended benchmark with further scenarios --- CMakeLists.txt | 11 ++ src/benchmark_add_1d.hpp | 2 +- src/benchmark_add_2d.hpp | 2 +- src/benchmark_iterators.hpp | 55 ++++++- src/benchmark_lazy_evaluation.hpp | 119 +++++++++++++++ src/benchmark_padding.hpp | 60 ++++++++ src/benchmark_scalar_assignment.hpp | 16 +- src/benchmark_views.hpp | 221 +++++++++++++++++++++++----- src/main.cpp | 5 + 9 files changed, 453 insertions(+), 38 deletions(-) create mode 100644 src/benchmark_lazy_evaluation.hpp create mode 100644 src/benchmark_padding.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cafde74..11ab143 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) # ===================== option(BENCHMARK_XTENSOR "benchmark against xtensor" ON) +option(BENCHMARK_CLIKE "benchmark against a C-like reference" OFF) option(BENCHMARK_EIGEN "benchmark against eigen" OFF) option(BENCHMARK_BLITZ "benchmark against Blitz" OFF) option(BENCHMARK_ARMADILLO "benchmark agains Armadillo" OFF) @@ -29,6 +30,7 @@ option(BUILD_EXTERNAL_GOOGLEBENCHMARK "Download and build google benchmark" OFF) if(BENCHMARK_ALL) set(BENCHMARK_XTENSOR ON) + set(BENCHMARK_CLIKE ON) set(BENCHMARK_EIGEN ON) set(BENCHMARK_BLITZ ON) set(BENCHMARK_ARMADILLO ON) @@ -87,6 +89,8 @@ set(XTENSOR_BENCHMARK src/benchmark_constructor.hpp src/benchmark_scalar_assignment.hpp src/benchmark_iterators.hpp + src/benchmark_lazy_evaluation.hpp + src/benchmark_padding.hpp src/main.cpp ) @@ -112,6 +116,10 @@ if(BENCHMARK_XTENSOR) target_compile_definitions(${XTENSOR_BENCHMARK_TARGET} PRIVATE HAS_XTENSOR=1) endif() +if(BENCHMARK_CLIKE) + target_compile_definitions(${XTENSOR_BENCHMARK_TARGET} PRIVATE HAS_CLIKE=1) +endif() + if(BENCHMARK_EIGEN) find_package(Eigen3 REQUIRED NO_MODULE) target_compile_definitions(${XTENSOR_BENCHMARK_TARGET} PRIVATE HAS_EIGEN=1 EIGEN_FAST_MATH=1) @@ -153,6 +161,9 @@ if(BENCHMARK_XTENSOR) message("Found xtensor : ${xtensor_INCLUDE_DIRS}") message("Found xsimd : ${xsimd_INCLUDE_DIRS}\n\n") endif() +if(BENCHMARK_CLIKE) + message("Will use C-Like : yes") +endif() if(BENCHMARK_EIGEN) message("Found eigen : ${EIGEN3_INCLUDE_DIR}") endif() diff --git a/src/benchmark_add_1d.hpp b/src/benchmark_add_1d.hpp index db04841..0850d5c 100644 --- a/src/benchmark_add_1d.hpp +++ b/src/benchmark_add_1d.hpp @@ -39,7 +39,7 @@ static_assert(false, "NOT VECTORIZING"); #include #endif -#define RANGE 3, 1000 +#define RANGE 16, 128*128 #define MULTIPLIER 8 diff --git a/src/benchmark_add_2d.hpp b/src/benchmark_add_2d.hpp index 56e4a7b..065dff2 100644 --- a/src/benchmark_add_2d.hpp +++ b/src/benchmark_add_2d.hpp @@ -36,7 +36,7 @@ #include #endif -#define RANGE 3, 1000 +#define RANGE 16, 1024 #define MULTIPLIER 8 diff --git a/src/benchmark_iterators.hpp b/src/benchmark_iterators.hpp index dbd9d0a..8e03e5e 100644 --- a/src/benchmark_iterators.hpp +++ b/src/benchmark_iterators.hpp @@ -16,6 +16,10 @@ #include "xtensor/xarray.hpp" #endif +#ifdef HAS_CLIKE +#include +#endif + #ifdef HAS_EIGEN #include #include @@ -25,10 +29,9 @@ #include #endif -#define RANGE 3, 1000 +#define RANGE 16, 1024 #define MULTIPLIER 8 - #ifdef HAS_XTENSOR void IterateWhole2D_XTensor(benchmark::State& state) { @@ -43,6 +46,54 @@ void IterateWhole2D_XTensor(benchmark::State& state) } } BENCHMARK(IterateWhole2D_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void IterateWhole2DView_XTensor(benchmark::State& state) +{ + xt::xtensor vTensor({state.range(0), state.range(0)}); + auto vView = xt::view(vTensor, xt::all()); + for (auto _ : state) + { + double vTmp = 0.0; + for (auto it = vView.begin(); it != vView.end(); ++it) { + vTmp += *it; + } + benchmark::DoNotOptimize(vTmp); + } +} +BENCHMARK(IterateWhole2DView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void IterateWhole2DStridedView_XTensor(benchmark::State& state) +{ + xt::xtensor vTensor({state.range(0), state.range(0)}); + auto vView = xt::strided_view(vTensor, {xt::all()}); + for (auto _ : state) + { + double vTmp = 0.0; + for (auto it = vView.begin(); it != vView.end(); ++it) { + vTmp += *it; + } + benchmark::DoNotOptimize(vTmp); + } +} +BENCHMARK(IterateWhole2DStridedView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + +#ifdef HAS_CLIKE +void IterateWhole2D_CLike(benchmark::State& state) +{ + std::vector vTensor(state.range(0) * state.range(0)); + for (auto _ : state) + { + double vTmp = 0.0; + double* it = vTensor.data(); + double* end = vTensor.data() + vTensor.size(); + for (; it != end; ++it) { + vTmp += *it; + } + benchmark::DoNotOptimize(vTmp); + } +} +BENCHMARK(IterateWhole2D_CLike)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif //#ifdef HAS_EIGEN diff --git a/src/benchmark_lazy_evaluation.hpp b/src/benchmark_lazy_evaluation.hpp new file mode 100644 index 0000000..27b94e7 --- /dev/null +++ b/src/benchmark_lazy_evaluation.hpp @@ -0,0 +1,119 @@ +/*************************************************************************** +* Copyright (c) 2016, Johan Mabille, Sylvain Corlay and Wolf Vollprecht * +* * +* Distributed under the terms of the BSD 3-Clause License. * +* * +* The full license is in the file LICENSE, distributed with this software. * +****************************************************************************/ + +#include + +#ifdef HAS_XTENSOR +#include "xtensor/xnoalias.hpp" +#include "xtensor/xio.hpp" +#include "xtensor/xrandom.hpp" +#include "xtensor/xtensor.hpp" +#include "xtensor/xarray.hpp" +#endif + +#define RANGE 1, 10 +#define MULTIPLIER 2 +#define ARRAY_SIZE 1000 + +#ifdef HAS_XTENSOR +void Add2DLazy_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor a = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor b = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + + double percentage = static_cast(state.range(0)) / 10; + size_t reducedSize = static_cast(percentage * a.size()); + double tmp = 0.0; + + for (auto _ : state) + { + auto&& res = (a + b); + for (int i = 0; i < reducedSize; ++i){ + tmp += res[i]; + } + benchmark::DoNotOptimize(tmp); + } +} +BENCHMARK(Add2DLazy_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Add2DEval_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor a = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor b = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + + double percentage = static_cast(state.range(0)) / 10; + size_t reducedSize = static_cast(percentage * a.size()); + double tmp = 0.0; + + for (auto _ : state) + { + auto&& res = xt::eval(a + b); + for (int i = 0; i < reducedSize; ++i){ + tmp += res[i]; + } + benchmark::DoNotOptimize(tmp); + } +} +BENCHMARK(Add2DEval_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void AddDivide2DLazy_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor a = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor b = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor c = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor d = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + + double percentage = static_cast(state.range(0)) / 10; + size_t reducedSize = static_cast(percentage * a.size()); + double tmp = 0.0; + + for (auto _ : state) + { + auto&& res = (a + b + c) / d; + for (int i = 0; i < reducedSize; ++i){ + tmp += res[i]; + } + benchmark::DoNotOptimize(a.data()); + } +} +BENCHMARK(AddDivide2DLazy_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void AddDivide2DEval_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor a = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor b = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor c = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + xtensor d = random::rand({ARRAY_SIZE, ARRAY_SIZE}); + + double percentage = static_cast(state.range(0)) / 10; + size_t reducedSize = static_cast(percentage * a.size()); + double tmp = 0.0; + + for (auto _ : state) + { + auto&& res = xt::eval((a + b + c) / d); + for (int i = 0; i < reducedSize; ++i){ + tmp += res[i]; + } + benchmark::DoNotOptimize(res.data()); + } +} +BENCHMARK(AddDivide2DEval_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + +#undef RANGE +#undef MULTIPLIER + diff --git a/src/benchmark_padding.hpp b/src/benchmark_padding.hpp new file mode 100644 index 0000000..b0d4794 --- /dev/null +++ b/src/benchmark_padding.hpp @@ -0,0 +1,60 @@ +#include + +#ifdef HAS_XTENSOR +#include +#include +#include +#include "xtensor/xrandom.hpp" +#include +#include +#endif + +#define RANGE 16, 1000 +#define MULTIPLIER 8 + +#ifdef HAS_XTENSOR +void Pad2dConstant_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor vInput = random::rand({state.range(0), state.range(0)}); + + for (auto _ : state) + { + xtensor vOutput = pad(vInput, {{100, 100}, {100, 100}}, pad_mode::constant, 5); + benchmark::DoNotOptimize(vOutput.data()); + } +} +BENCHMARK(Pad2dConstant_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Pad2dMirror_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor vInput = random::rand({state.range(0), state.range(0)}); + + for (auto _ : state) + { + xtensor vOutput = pad(vInput, {{100, 100}, {100, 100}}, pad_mode::symmetric, 5); + benchmark::DoNotOptimize(vOutput.data()); + } +} +BENCHMARK(Pad2dMirror_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Pad2dCyclic_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor vInput = random::rand({state.range(0), state.range(0)}); + + for (auto _ : state) + { + xtensor vOutput = pad(vInput, {{100, 100}, {100, 100}}, pad_mode::periodic, 5); + benchmark::DoNotOptimize(vOutput.data()); + } +} +BENCHMARK(Pad2dCyclic_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + +#undef RANGE +#undef MULTIPLIER diff --git a/src/benchmark_scalar_assignment.hpp b/src/benchmark_scalar_assignment.hpp index 79f8911..bdf2ba1 100644 --- a/src/benchmark_scalar_assignment.hpp +++ b/src/benchmark_scalar_assignment.hpp @@ -25,7 +25,7 @@ #include #endif -#define RANGE 3, 1000 +#define RANGE 16, 1024 #define MULTIPLIER 8 @@ -42,6 +42,20 @@ void AssignScalar2D_XTensor(benchmark::State& state) } } BENCHMARK(AssignScalar2D_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +void AssignScalar2DLoop_XTensor(benchmark::State& state) +{ + xt::xtensor vTensor({state.range(0), state.range(0)}); + double value = 0.0; + for (auto _ : state) + { + for (size_t i = 0; i < vTensor.shape(0); ++i) + for (size_t j = 0; j < vTensor.shape(1); ++j) + vTensor(i, j) = value; + value += 1.0; + benchmark::DoNotOptimize(vTensor.data()); + } +} +BENCHMARK(AssignScalar2DLoop_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif #ifdef HAS_EIGEN diff --git a/src/benchmark_views.hpp b/src/benchmark_views.hpp index 71b30b2..6ae6096 100644 --- a/src/benchmark_views.hpp +++ b/src/benchmark_views.hpp @@ -55,46 +55,64 @@ void Add2dView_XTensor(benchmark::State& state) } } BENCHMARK(Add2dView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); -#endif -#ifdef HAS_EIGEN -void Add2dView_Eigen(benchmark::State& state) +void Assign2dView_XTensor(benchmark::State& state) { - using namespace Eigen; - MatrixXd vA = MatrixXd::Random(state.range(0), state.range(0)); - MatrixXd vB = MatrixXd::Random(state.range(0), state.range(0)); + using namespace xt; - auto vAView = vA.topLeftCorner(state.range(0), state.range(0)); - auto vBView = vB.topLeftCorner(state.range(0), state.range(0)); + xtensor vA = random::rand({state.range(0), state.range(0)}); + xtensor vB = random::rand({state.range(0), state.range(0)}); + + auto vAView = xt::view(vA, all(), all()); for (auto _ : state) { - MatrixXd vRes(state.range(0), state.range(0)); - vRes.noalias() = vAView + vBView; - benchmark::DoNotOptimize(vRes.data()); + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); } } -BENCHMARK(Add2dView_Eigen)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +BENCHMARK(Assign2dView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); -//void Add1dMap_Eigen(benchmark::State& state) -//{ -// using namespace Eigen; -// MatrixXd vA = VectorXd::Random(state.range(0)); -// MatrixXd vB = VectorXd::Random(state.range(0)); -// -// auto vAView = Map>(vA.data(), vA.size()); -// auto vBView = Map>(vB.data(), vB.size()); -// -// for (auto _ : state) -// { -// VectorXd vRes(vAView + vBView); -// benchmark::DoNotOptimize(vRes.data()); -// } -//} -//BENCHMARK(Add1dMap_Eigen)->RangeMultiplier(MULTIPLIER)->Range(RANGE); -#endif +void Assign2dNotContiguousHalfView_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size/2, size/2}); + + auto vAView = xt::view(vA, range(size/4, size/4 + size/2), + range(size/4, size/4 + size/2)); + + for (auto _ : state) + { + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dNotContiguousHalfView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dContiguousHalfView_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size/4, size}); + + auto vAView = xt::view(vA, range(0, size/4), + range(0, size)); + + for (auto _ : state) + { + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dContiguousHalfView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); -#ifdef HAS_XTENSOR void Add2dStridedView_XTensor(benchmark::State& state) { using namespace xt; @@ -113,6 +131,63 @@ void Add2dStridedView_XTensor(benchmark::State& state) } BENCHMARK(Add2dStridedView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +void Assign2dStridedView_XTensor(benchmark::State& state) +{ + using namespace xt; + + xtensor vA = random::rand({state.range(0), state.range(0)}); + xtensor vB = random::rand({state.range(0), state.range(0)}); + + auto vAView = xt::strided_view(vA, {all(), all()}); + + for (auto _ : state) + { + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dStridedView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dNotContiguousHalfStridedView_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size/2, size/2}); + + auto vAView = xt::strided_view(vA, {range(size/4, size/4 + size/2), + range(size/4, size/4 + size/2)}); + + for (auto _ : state) + { + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dNotContiguousHalfStridedView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dContiguousHalfStridedView_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size/4, size}); + + auto vAView = xt::strided_view(vA, {range(0, size/4), + range(0, size)}); + + for (auto _ : state) + { + xt::noalias(vAView) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dContiguousHalfStridedView_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + void Add2dDynamicView_XTensor(benchmark::State& state) { using namespace xt; @@ -154,9 +229,11 @@ void Add2dLoop_XTensor(benchmark::State& state) { using namespace xt; - xtensor vA = random::rand({state.range(0), state.range(0)}); - xtensor vB = random::rand({state.range(0), state.range(0)}); - std::array vShape = {static_cast(state.range(0)), static_cast(state.range(0))}; + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size, size}); + std::array vShape = {static_cast(size), static_cast(size)}; for (auto _ : state) { xtensor vRes(vShape); @@ -171,8 +248,86 @@ void Add2dLoop_XTensor(benchmark::State& state) } } BENCHMARK(Add2dLoop_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dLoop_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size, size}); + for (auto _ : state) + { + for (std::size_t i = 0; i < size; ++i) + { + for (std::size_t j = 0; j < size; ++j) + { + vA(i, j) = vB(i, j); + } + } + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dLoop_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dNotContiguousHalfLoop_XTensor(benchmark::State& state) +{ + using namespace xt; + + size_t size = state.range(0); + + xtensor vA = random::rand({size, size}); + xtensor vB = random::rand({size/2, size/2}); + for (auto _ : state) + { + for (std::size_t i = 0; i < size / 2; ++i) { + for (std::size_t j = 0; j < size / 2; ++j) { + vA(i + size / 4, j + size / 4) = vB(i, j); + } + } + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dNotContiguousHalfLoop_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_EIGEN +void Add2dView_Eigen(benchmark::State& state) +{ + using namespace Eigen; + MatrixXd vA = MatrixXd::Random(state.range(0), state.range(0)); + MatrixXd vB = MatrixXd::Random(state.range(0), state.range(0)); + + auto vAView = vA.topLeftCorner(state.range(0), state.range(0)); + auto vBView = vB.topLeftCorner(state.range(0), state.range(0)); + + for (auto _ : state) + { + MatrixXd vRes(state.range(0), state.range(0)); + vRes.noalias() = vAView + vBView; + benchmark::DoNotOptimize(vRes.data()); + } +} +BENCHMARK(Add2dView_Eigen)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +//void Add1dMap_Eigen(benchmark::State& state) +//{ +// using namespace Eigen; +// MatrixXd vA = VectorXd::Random(state.range(0)); +// MatrixXd vB = VectorXd::Random(state.range(0)); +// +// auto vAView = Map>(vA.data(), vA.size()); +// auto vBView = Map>(vB.data(), vB.size()); +// +// for (auto _ : state) +// { +// VectorXd vRes(vAView + vBView); +// benchmark::DoNotOptimize(vRes.data()); +// } +//} +//BENCHMARK(Add1dMap_Eigen)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif #undef RANGE #undef MULTIPLIER diff --git a/src/main.cpp b/src/main.cpp index 0d8cac7..9c63ea1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,6 +18,8 @@ #include "benchmark_constructor.hpp" #include "benchmark_scalar_assignment.hpp" #include "benchmark_iterators.hpp" +#include "benchmark_lazy_evaluation.hpp" +#include "benchmark_padding.hpp" #ifdef XTENSOR_USE_XSIMD @@ -50,4 +52,7 @@ int main(int argc, char** argv) benchmark::Initialize(&argc, argv); if (benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; benchmark::RunSpecifiedBenchmarks(); + + return 0; } + From 935693c664fc8561186e1c4bc9efb3837738c45b Mon Sep 17 00:00:00 2001 From: Mario Emmenlauer Date: Sun, 16 Jun 2019 15:24:41 +0200 Subject: [PATCH 2/2] Added optionally a number of Vigra benchmarks --- CMakeLists.txt | 11 +++++ src/benchmark_add_1d.hpp | 21 ++++++++++ src/benchmark_add_2d.hpp | 21 ++++++++++ src/benchmark_constructor.hpp | 32 ++++++++++++++ src/benchmark_iterators.hpp | 22 ++++++++++ src/benchmark_scalar_assignment.hpp | 21 ++++++++++ src/benchmark_views.hpp | 65 +++++++++++++++++++++++++++++ 7 files changed, 193 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 11ab143..be39119 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) option(BENCHMARK_XTENSOR "benchmark against xtensor" ON) option(BENCHMARK_CLIKE "benchmark against a C-like reference" OFF) +option(BENCHMARK_VIGRA "benchmark against Vigra" OFF) option(BENCHMARK_EIGEN "benchmark against eigen" OFF) option(BENCHMARK_BLITZ "benchmark against Blitz" OFF) option(BENCHMARK_ARMADILLO "benchmark agains Armadillo" OFF) @@ -31,6 +32,7 @@ option(BUILD_EXTERNAL_GOOGLEBENCHMARK "Download and build google benchmark" OFF) if(BENCHMARK_ALL) set(BENCHMARK_XTENSOR ON) set(BENCHMARK_CLIKE ON) + set(BENCHMARK_VIGRA ON) set(BENCHMARK_EIGEN ON) set(BENCHMARK_BLITZ ON) set(BENCHMARK_ARMADILLO ON) @@ -126,6 +128,12 @@ if(BENCHMARK_EIGEN) target_link_libraries(${XTENSOR_BENCHMARK_TARGET} Eigen3::Eigen) endif() +if(BENCHMARK_VIGRA) + find_package(Vigra 1.11.1 REQUIRED NO_MODULE) + target_compile_definitions(${XTENSOR_BENCHMARK_TARGET} PRIVATE HAS_VIGRA=1) + target_link_libraries(${XTENSOR_BENCHMARK_TARGET} vigraimpex) +endif() + if(BENCHMARK_BLITZ) find_package(Blitz REQUIRED) target_compile_definitions(${XTENSOR_BENCHMARK_TARGET} PRIVATE HAS_BLITZ=1) @@ -167,6 +175,9 @@ endif() if(BENCHMARK_EIGEN) message("Found eigen : ${EIGEN3_INCLUDE_DIR}") endif() +if(BENCHMARK_VIGRA) + message("Found Vigra : ${Vigra_INCLUDES}") +endif() if(BENCHMARK_BLITZ) message("Found Blitz : ${BLITZ_INCLUDES} | ${BLITZ_LIBRARIES}") endif() diff --git a/src/benchmark_add_1d.hpp b/src/benchmark_add_1d.hpp index 0850d5c..ded6cb9 100644 --- a/src/benchmark_add_1d.hpp +++ b/src/benchmark_add_1d.hpp @@ -39,6 +39,11 @@ static_assert(false, "NOT VECTORIZING"); #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 16, 128*128 #define MULTIPLIER 8 @@ -90,6 +95,22 @@ void Add1D_Blitz(benchmark::State& state) BENCHMARK(Add1D_Blitz)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void Add1D_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + vigra::MultiArray<1, double> vA(state.range(0)); + vigra::MultiArray<1, double> vB(state.range(0)); + for (auto _ : state) + { + vigra::MultiArray<1, double> vRes(state.range(0)); + vRes = vA + vB; + benchmark::DoNotOptimize(vRes.data()); + } +} +BENCHMARK(Add1D_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #ifdef HAS_ARMADILLO void Add1D_Arma(benchmark::State& state) { diff --git a/src/benchmark_add_2d.hpp b/src/benchmark_add_2d.hpp index 065dff2..7d24d79 100644 --- a/src/benchmark_add_2d.hpp +++ b/src/benchmark_add_2d.hpp @@ -36,6 +36,11 @@ #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 16, 1024 #define MULTIPLIER 8 @@ -118,6 +123,22 @@ void Add2D_Pythonic(benchmark::State& state) BENCHMARK(Add2D_Pythonic)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void Add2D_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + vigra::MultiArray<2, double> vA(state.range(0), state.range(0)); + vigra::MultiArray<2, double> vB(state.range(0), state.range(0)); + for (auto _ : state) + { + vigra::MultiArray<2, double> vRes(state.range(0), state.range(0)); + vRes = vA + vB; + benchmark::DoNotOptimize(vRes.data()); + } +} +BENCHMARK(Add2D_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #undef RANGE #undef MULTIPLIER diff --git a/src/benchmark_constructor.hpp b/src/benchmark_constructor.hpp index a35667c..1df2941 100644 --- a/src/benchmark_constructor.hpp +++ b/src/benchmark_constructor.hpp @@ -25,6 +25,11 @@ #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 3, 1000 #define MULTIPLIER 8 @@ -66,6 +71,19 @@ void Construct2D_Blitz(benchmark::State& state) BENCHMARK(Construct2D_Blitz)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void Construct2D_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + for (auto _ : state) + { + vigra::MultiArray<2, double> vArray(state.range(0), state.range(0)); + benchmark::DoNotOptimize(vArray); + } +} +BENCHMARK(Construct2D_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #ifdef HAS_XTENSOR void ConstructRandom2D_XTensor(benchmark::State& state) { @@ -108,6 +126,20 @@ void ConstructView2d_XTensor(benchmark::State& state) BENCHMARK(ConstructView2d_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void ConstructView2d_Vigra(benchmark::State& state) +{ + vigra::MultiArray<2,double> vA(state.range(0), state.range(0)); + + for (auto _ : state) + { + vigra::MultiArrayView<2,double> vAView = vA.subarray({0, 0}, {state.range(0), state.range(0)}); + benchmark::DoNotOptimize(vAView); + } +} +BENCHMARK(ConstructView2d_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #ifdef HAS_EIGEN void ConstructView2d_Eigen(benchmark::State& state) { diff --git a/src/benchmark_iterators.hpp b/src/benchmark_iterators.hpp index 8e03e5e..ee6eb51 100644 --- a/src/benchmark_iterators.hpp +++ b/src/benchmark_iterators.hpp @@ -29,6 +29,11 @@ #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 16, 1024 #define MULTIPLIER 8 @@ -130,6 +135,23 @@ void IterateWhole2D_Blitz(benchmark::State& state) BENCHMARK(IterateWhole2D_Blitz)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void IterateWhole2D_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + vigra::MultiArray<2, double> vArray(state.range(0), state.range(0)); + for (auto _ : state) + { + double vTmp = 0.0; + for (auto it = vArray.begin(); it != vArray.end(); ++it) { + vTmp += *it; + } + benchmark::DoNotOptimize(vTmp); + } +} +BENCHMARK(IterateWhole2D_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #undef RANGE #undef MULTIPLIER diff --git a/src/benchmark_scalar_assignment.hpp b/src/benchmark_scalar_assignment.hpp index bdf2ba1..c29c803 100644 --- a/src/benchmark_scalar_assignment.hpp +++ b/src/benchmark_scalar_assignment.hpp @@ -25,6 +25,11 @@ #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 16, 1024 #define MULTIPLIER 8 @@ -90,6 +95,22 @@ void AssignScalar2D_Blitz(benchmark::State& state) BENCHMARK(AssignScalar2D_Blitz)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void AssignScalar2D_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + vigra::MultiArray<2, double> vArray(state.range(0), state.range(0)); + double value = 0.0; + for (auto _ : state) + { + vArray = value; + value += 1.0; + benchmark::DoNotOptimize(vArray); + } +} +BENCHMARK(AssignScalar2D_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #undef RANGE #undef MULTIPLIER diff --git a/src/benchmark_views.hpp b/src/benchmark_views.hpp index 6ae6096..2873cce 100644 --- a/src/benchmark_views.hpp +++ b/src/benchmark_views.hpp @@ -33,6 +33,11 @@ #include #endif +#ifdef HAS_VIGRA +#include "vigra/multi_array.hxx" +#include "vigra/multi_math.hxx" +#endif + #define RANGE 3, 1000 #define MULTIPLIER 8 @@ -292,6 +297,66 @@ void Assign2dNotContiguousHalfLoop_XTensor(benchmark::State& state) BENCHMARK(Assign2dNotContiguousHalfLoop_XTensor)->RangeMultiplier(MULTIPLIER)->Range(RANGE); #endif +#ifdef HAS_VIGRA +void Add2dView_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + + vigra::MultiArray<2,double> vA(state.range(0), state.range(0)); + vigra::MultiArray<2,double> vB(state.range(0), state.range(0)); + + vigra::MultiArrayView<2,double> vAView = vA.subarray({0, 0}, {state.range(0), state.range(0)}); + vigra::MultiArrayView<2,double> vBView = vB.subarray({0, 0}, {state.range(0), state.range(0)}); + + for (auto _ : state) + { + vigra::MultiArray<2,double> vRes(vAView + vBView); + benchmark::DoNotOptimize(vRes.data()); + } +} +BENCHMARK(Add2dView_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dView_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + + vigra::MultiArray<2,double> vA(state.range(0), state.range(0)); + vigra::MultiArray<2,double> vB(state.range(0), state.range(0)); + + vA = 1; + vB = 2; + + vigra::MultiArrayView<2,double> vAView = vA.subarray({0, 0}, {state.range(0), state.range(0)}); + + for (auto _ : state) + { + vAView = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dView_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); + +void Assign2dHalfView_Vigra(benchmark::State& state) +{ + using namespace vigra::multi_math; + + size_t size = state.range(0); + + vigra::MultiArray<2,double> vA(size, size); + vigra::MultiArray<2,double> vB(size/2, size/2); + + vA = 1; + vB = 2; + + for (auto _ : state) + { + vA.subarray({size/4, size/4}, {size/4 + size/2, size/4 + size/2}) = vB; + benchmark::DoNotOptimize(vA.data()); + } +} +BENCHMARK(Assign2dHalfView_Vigra)->RangeMultiplier(MULTIPLIER)->Range(RANGE); +#endif + #ifdef HAS_EIGEN void Add2dView_Eigen(benchmark::State& state) {