From 3a0de8cbc84952aa47a8672fec3dd0ffdd77d8d8 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 26 Aug 2024 11:03:34 +0300 Subject: [PATCH 1/8] benchmark --- benchmarks/src/minmax_element.cpp | 151 ++++++++++++++++-------------- 1 file changed, 80 insertions(+), 71 deletions(-) diff --git a/benchmarks/src/minmax_element.cpp b/benchmarks/src/minmax_element.cpp index 812b8c318b0..b3dfd9b073d 100644 --- a/benchmarks/src/minmax_element.cpp +++ b/benchmarks/src/minmax_element.cpp @@ -8,6 +8,7 @@ #include #include #include +#include enum class Op { Min, @@ -20,9 +21,9 @@ enum class Op { using namespace std; -template +template void bm(benchmark::State& state) { - T a[Size]; + vector a(static_cast(state.range())); mt19937 gen(84710); @@ -35,6 +36,8 @@ void bm(benchmark::State& state) { } for (auto _ : state) { + benchmark::DoNotOptimize(a); + if constexpr (Operation == Op::Min) { benchmark::DoNotOptimize(ranges::min_element(a)); } else if constexpr (Operation == Op::Max) { @@ -51,75 +54,81 @@ void bm(benchmark::State& state) { } } -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); - -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); -BENCHMARK(bm); +void common_arg(auto bm) { + bm->Arg(8021); + // AVX tail tests + bm->Arg(63)->Arg(31)->Arg(15)->Arg(7); +} + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); + +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); +BENCHMARK(bm)->Apply(common_arg); BENCHMARK_MAIN(); From 6ae3ab8c8a3332b0e1deb1f9200f5d61b1093bec Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 26 Aug 2024 11:06:59 +0300 Subject: [PATCH 2/8] values --- stl/src/vector_algorithms.cpp | 100 ++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 22 deletions(-) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index c86b96871f9..2df003f1ef0 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -548,9 +548,10 @@ namespace { #ifndef _M_ARM64EC struct _Minmax_traits_sse_base { - static constexpr bool _Vectorized = true; - static constexpr size_t _Vec_size = 16; - static constexpr size_t _Vec_mask = 0xF; + static constexpr bool _Vectorized = true; + static constexpr size_t _Vec_size = 16; + static constexpr size_t _Vec_mask = 0xF; + static constexpr size_t _Tail_mask = 0; static __m128i _Zero() noexcept { return _mm_setzero_si128(); @@ -596,6 +597,18 @@ namespace { _mm256_zeroupper(); } }; + + struct _Minmax_traits_avx_i_base : _Minmax_traits_avx_base { + static constexpr size_t _Tail_mask = 0x1C; + + static __m256i _Blendval(const __m256i _Px1, const __m256i _Px2, const __m256i _Msk) noexcept { + return _mm256_blendv_epi8(_Px1, _Px2, _Msk); + } + + static __m256i _Load_mask(const void* _Src, const __m256i _Mask) noexcept { + return _mm256_maskload_epi32(reinterpret_cast(_Src), _Mask); + } + }; #endif // !defined(_M_ARM64EC) struct _Minmax_traits_1_base { @@ -702,7 +715,7 @@ namespace { } }; - struct _Minmax_traits_1_avx : _Minmax_traits_1_base, _Minmax_traits_avx_base { + struct _Minmax_traits_1_avx : _Minmax_traits_1_base, _Minmax_traits_avx_i_base { static __m256i _Load(const void* _Src) noexcept { return _mm256_loadu_si256(reinterpret_cast(_Src)); } @@ -898,7 +911,7 @@ namespace { } }; - struct _Minmax_traits_2_avx : _Minmax_traits_2_base, _Minmax_traits_avx_base { + struct _Minmax_traits_2_avx : _Minmax_traits_2_base, _Minmax_traits_avx_i_base { static __m256i _Load(const void* _Src) noexcept { return _mm256_loadu_si256(reinterpret_cast(_Src)); } @@ -1091,7 +1104,7 @@ namespace { } }; - struct _Minmax_traits_4_avx : _Minmax_traits_4_base, _Minmax_traits_avx_base { + struct _Minmax_traits_4_avx : _Minmax_traits_4_base, _Minmax_traits_avx_i_base { static __m256i _Load(const void* _Src) noexcept { return _mm256_loadu_si256(reinterpret_cast(_Src)); } @@ -1279,7 +1292,7 @@ namespace { } }; - struct _Minmax_traits_8_avx : _Minmax_traits_8_base, _Minmax_traits_avx_base { + struct _Minmax_traits_8_avx : _Minmax_traits_8_base, _Minmax_traits_avx_i_base { static __m256i _Load(const void* _Src) noexcept { return _mm256_loadu_si256(reinterpret_cast(_Src)); } @@ -1471,10 +1484,20 @@ namespace { }; struct _Minmax_traits_f_avx : _Minmax_traits_f_base, _Minmax_traits_avx_base { + static constexpr size_t _Tail_mask = 0xC; + + static __m256 _Blendval(const __m256 _Px1, const __m256 _Px2, const __m256i _Msk) noexcept { + return _mm256_blendv_ps(_Px1, _Px2, _mm256_castsi256_ps(_Msk)); + } + static __m256 _Load(const void* _Src) noexcept { return _mm256_loadu_ps(reinterpret_cast(_Src)); } + static __m256 _Load_mask(const void* _Src, const __m256i _Mask) noexcept { + return _mm256_maskload_ps(reinterpret_cast(_Src), _Mask); + } + static __m256 _Sign_correction(const __m256 _Val, bool) noexcept { return _Val; } @@ -1629,10 +1652,20 @@ namespace { }; struct _Minmax_traits_d_avx : _Minmax_traits_d_base, _Minmax_traits_avx_base { + static constexpr size_t _Tail_mask = 0x8; + + static __m256d _Blendval(const __m256d _Px1, const __m256d _Px2, const __m256i _Msk) noexcept { + return _mm256_blendv_pd(_Px1, _Px2, _mm256_castsi256_pd(_Msk)); + } + static __m256d _Load(const void* _Src) noexcept { return _mm256_loadu_pd(reinterpret_cast(_Src)); } + static __m256d _Load_mask(const void* _Src, const __m256i _Mask) noexcept { + return _mm256_maskload_pd(reinterpret_cast(_Src), _Mask); + } + static __m256d _Sign_correction(const __m256d _Val, bool) noexcept { return _Val; } @@ -1992,10 +2025,11 @@ namespace { #ifdef _M_ARM64EC static_assert(false, "No vectorization for _M_ARM64EC yet"); #else // ^^^ defined(_M_ARM64EC) / !defined(_M_ARM64EC) vvv - const size_t _Sse_byte_size = _Byte_length(_First, _Last) & ~_Traits::_Vec_mask; + const size_t _Total_size_bytes = _Byte_length(_First, _Last); + const size_t _Vec_byte_size = _Total_size_bytes & ~_Traits::_Vec_mask; const void* _Stop_at = _First; - _Advance_bytes(_Stop_at, _Sse_byte_size); + _Advance_bytes(_Stop_at, _Vec_byte_size); auto _Cur_vals = _Traits::_Load(_First); @@ -2009,6 +2043,24 @@ namespace { auto _Cur_vals_min = _Cur_vals; // vector of vertical minimum values auto _Cur_vals_max = _Cur_vals; // vector of vertical maximum values + const auto _Update_min_max = [&](const auto _Cur_vals) noexcept { + if constexpr ((_Mode & _Mode_min) != 0) { + if constexpr (_Sign || _Sign_correction) { + _Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals); // Update the current minimum + } else { + _Cur_vals_min = _Traits::_Min_u(_Cur_vals_min, _Cur_vals); // Update the current minimum + } + } + + if constexpr ((_Mode & _Mode_max) != 0) { + if constexpr (_Sign || _Sign_correction) { + _Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals); // Update the current maximum + } else { + _Cur_vals_max = _Traits::_Max_u(_Cur_vals_max, _Cur_vals); // Update the current maximum + } + } + }; + for (;;) { _Advance_bytes(_First, _Traits::_Vec_size); @@ -2021,22 +2073,26 @@ namespace { _Cur_vals = _Traits::_Sign_correction(_Cur_vals, false); } - if constexpr ((_Mode & _Mode_min) != 0) { - if constexpr (_Sign || _Sign_correction) { - _Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals); // Update the current minimum - } else { - _Cur_vals_min = _Traits::_Min_u(_Cur_vals_min, _Cur_vals); // Update the current minimum - } - } + _Update_min_max(_Cur_vals); + } else { + if constexpr (_Traits::_Tail_mask != 0) { + const size_t _Tail_byte_size = _Total_size_bytes & _Traits::_Tail_mask; + if (_Tail_byte_size != 0) { + const auto _Tail_mask = _Avx2_tail_mask_32(_Tail_byte_size >> 2); + auto _Tail_vals = _Traits::_Load_mask(_First, _Tail_mask); + + if constexpr (_Sign_correction) { + _Tail_vals = _Traits::_Sign_correction(_Tail_vals, false); + } - if constexpr ((_Mode & _Mode_max) != 0) { - if constexpr (_Sign || _Sign_correction) { - _Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals); // Update the current maximum - } else { - _Cur_vals_max = _Traits::_Max_u(_Cur_vals_max, _Cur_vals); // Update the current maximum + _Tail_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask); + + _Update_min_max(_Tail_vals); } + + _Advance_bytes(_First, _Tail_byte_size); } - } else { + // Reached end. Compute horizontal min and/or max. if constexpr ((_Mode & _Mode_min) != 0) { From 827b74dac99ed045bb84e527b58f2e51de322a2d Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 26 Aug 2024 18:05:08 +0300 Subject: [PATCH 3/8] indices --- stl/src/vector_algorithms.cpp | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 2df003f1ef0..c2571fd079d 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -1849,6 +1849,61 @@ namespace { _Cur_vals_max = _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum } } else { + if constexpr (_Traits::_Tail_mask != 0) { + const size_t _Remaining_byte_size = _Byte_length(_First, _Last); + bool _Last_portion; + + if constexpr (_Traits::_Has_portion_max) { + _Last_portion = (_Remaining_byte_size & ~_Traits::_Vec_mask) == 0; + } else { + _Last_portion = true; + } + + const size_t _Tail_byte_size = _Remaining_byte_size & _Traits::_Tail_mask; + + if (_Last_portion && _Tail_byte_size != 0) { + const auto _Tail_mask = _Avx2_tail_mask_32(_Tail_byte_size >> 2); + const auto _Tail_vals = + _Traits::_Sign_correction(_Traits::_Load_mask(_First, _Tail_mask), _Sign); + _Cur_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask); + + if constexpr ((_Mode & _Mode_min) != 0) { + // Looking for the first occurrence of minimum, don't overwrite with newly found + // occurrences + auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min + _Cur_idx_min = _Traits::_Blend(_Cur_idx_min, _Cur_idx, + _mm256_and_si256(_Traits::_Mask_cast(_Is_less), + _Tail_mask)); // Remember their vertical indices + _Cur_vals_min = + _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum + } + + if constexpr (_Mode == _Mode_max) { + // Looking for the first occurrence of maximum, don't overwrite with newly found + // occurrences + const auto _Is_greater = + _Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max + _Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx, + _mm256_and_si256(_Traits::_Mask_cast(_Is_greater), + _Tail_mask)); // Remember their vertical indices + _Cur_vals_max = + _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum + } else if constexpr (_Mode == _Mode_both) { + // Looking for the last occurrence of maximum, do overwrite with newly found + // occurrences + const auto _Is_less = + _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max) + _Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx, + _mm256_andnot_si256( + _Traits::_Mask_cast(_Is_less), _Tail_mask)); // Remember their vertical indices + _Cur_vals_max = + _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum + } + + _Advance_bytes(_First, _Tail_byte_size); + } + } + // Reached end or indices wrap around point. // Compute horizontal min and/or max. Determine horizontal and vertical position of it. From e76261f67c2e1b3d098033659f4a305377eebe58 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Mon, 26 Aug 2024 20:43:50 +0300 Subject: [PATCH 4/8] Reduce sizes variety --- benchmarks/src/minmax_element.cpp | 142 +++++++++++++++--------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/benchmarks/src/minmax_element.cpp b/benchmarks/src/minmax_element.cpp index b3dfd9b073d..7eb266e7736 100644 --- a/benchmarks/src/minmax_element.cpp +++ b/benchmarks/src/minmax_element.cpp @@ -54,81 +54,81 @@ void bm(benchmark::State& state) { } } +template void common_arg(auto bm) { bm->Arg(8021); // AVX tail tests - bm->Arg(63)->Arg(31)->Arg(15)->Arg(7); + bm->Arg(63 / ElementSize); } -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); -BENCHMARK(bm)->Apply(common_arg); - +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); + +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); + +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); + +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); + +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); +BENCHMARK(bm)->Apply(common_arg<1>); + +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); +BENCHMARK(bm)->Apply(common_arg<2>); + +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); + +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); + +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); +BENCHMARK(bm)->Apply(common_arg<4>); + +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); +BENCHMARK(bm)->Apply(common_arg<8>); BENCHMARK_MAIN(); From 7f2d6d667b71ede3ff374a9cd0ff89520cd56f07 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 27 Aug 2024 14:10:01 +0300 Subject: [PATCH 5/8] reduce copypasta --- stl/src/vector_algorithms.cpp | 102 ++++++++++++++++------------------ 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index c2571fd079d..795a9af520d 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -1812,6 +1812,43 @@ namespace { auto _Cur_idx_max = _Traits::_Zero(); // vector of vertical maximum indices auto _Cur_idx = _Traits::_Zero(); // current vector of indices + const auto _Update_min_max = [&](const auto _Cur_vals, const auto _Blend_idx_0, + const auto _Blend_idx_1) noexcept { + if constexpr ((_Mode & _Mode_min) != 0) { + // Looking for the first occurrence of minimum, don't overwrite with newly found occurrences + const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min + // Remember their vertical indices + _Cur_idx_min = _Blend_idx_1(_Cur_idx_min, _Cur_idx, _Traits::_Mask_cast(_Is_less)); + _Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum + + (void) _Blend_idx_0; + } + + if constexpr (_Mode == _Mode_max) { + // Looking for the first occurrence of maximum, don't overwrite with newly found occurrences + const auto _Is_greater = _Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max + // Remember their vertical indices + _Cur_idx_max = _Blend_idx_1(_Cur_idx_max, _Cur_idx, _Traits::_Mask_cast(_Is_greater)); + _Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum + + (void) _Blend_idx_0; + } else if constexpr (_Mode == _Mode_both) { + // Looking for the last occurrence of maximum, do overwrite with newly found occurrences + const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max) + // Remember their vertical indices + _Cur_idx_max = _Blend_idx_0(_Cur_idx_max, _Cur_idx, _Traits::_Mask_cast(_Is_less)); + _Cur_vals_max = _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum + } + }; + + const auto _Blend_idx_0 = [](const auto _Prev, const auto _Cur, const auto _Mask) noexcept { + return _Traits::_Blend(_Cur, _Prev, _Mask); + }; + + const auto _Blend_idx_1 = [](const auto _Prev, const auto _Cur, const auto _Mask) noexcept { + return _Traits::_Blend(_Prev, _Cur, _Mask); + }; + for (;;) { _Advance_bytes(_First, _Traits::_Vec_size); @@ -1824,30 +1861,7 @@ namespace { // Load values and if unsigned adjust them to be signed (for signed vector comparisons) _Cur_vals = _Traits::_Sign_correction(_Traits::_Load(_First), _Sign); - if constexpr ((_Mode & _Mode_min) != 0) { - // Looking for the first occurrence of minimum, don't overwrite with newly found occurrences - const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min - _Cur_idx_min = _Traits::_Blend( - _Cur_idx_min, _Cur_idx, _Traits::_Mask_cast(_Is_less)); // Remember their vertical indices - _Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum - } - - if constexpr (_Mode == _Mode_max) { - // Looking for the first occurrence of maximum, don't overwrite with newly found occurrences - const auto _Is_greater = - _Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max - _Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx, - _Traits::_Mask_cast(_Is_greater)); // Remember their vertical indices - _Cur_vals_max = - _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum - } else if constexpr (_Mode == _Mode_both) { - // Looking for the last occurrence of maximum, do overwrite with newly found occurrences - const auto _Is_less = - _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max) - _Cur_idx_max = _Traits::_Blend(_Cur_idx, _Cur_idx_max, - _Traits::_Mask_cast(_Is_less)); // Remember their vertical indices - _Cur_vals_max = _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum - } + _Update_min_max(_Cur_vals, _Blend_idx_0, _Blend_idx_1); } else { if constexpr (_Traits::_Tail_mask != 0) { const size_t _Remaining_byte_size = _Byte_length(_First, _Last); @@ -1867,39 +1881,17 @@ namespace { _Traits::_Sign_correction(_Traits::_Load_mask(_First, _Tail_mask), _Sign); _Cur_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask); - if constexpr ((_Mode & _Mode_min) != 0) { - // Looking for the first occurrence of minimum, don't overwrite with newly found - // occurrences - auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_min, _Cur_vals); // _Cur_vals < _Cur_vals_min - _Cur_idx_min = _Traits::_Blend(_Cur_idx_min, _Cur_idx, - _mm256_and_si256(_Traits::_Mask_cast(_Is_less), - _Tail_mask)); // Remember their vertical indices - _Cur_vals_min = - _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum - } + const auto _Blend_idx_0_mask = [_Tail_mask](const auto _Prev, const auto _Cur, + const auto _Mask) noexcept { + return _Traits::_Blend(_Prev, _Cur, _mm256_andnot_si256(_Mask, _Tail_mask)); + }; - if constexpr (_Mode == _Mode_max) { - // Looking for the first occurrence of maximum, don't overwrite with newly found - // occurrences - const auto _Is_greater = - _Traits::_Cmp_gt(_Cur_vals, _Cur_vals_max); // _Cur_vals > _Cur_vals_max - _Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx, - _mm256_and_si256(_Traits::_Mask_cast(_Is_greater), - _Tail_mask)); // Remember their vertical indices - _Cur_vals_max = - _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum - } else if constexpr (_Mode == _Mode_both) { - // Looking for the last occurrence of maximum, do overwrite with newly found - // occurrences - const auto _Is_less = - _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max) - _Cur_idx_max = _Traits::_Blend(_Cur_idx_max, _Cur_idx, - _mm256_andnot_si256( - _Traits::_Mask_cast(_Is_less), _Tail_mask)); // Remember their vertical indices - _Cur_vals_max = - _Traits::_Max(_Cur_vals, _Cur_vals_max, _Is_less); // Update the current maximum - } + const auto _Blend_idx_1_mask = [_Tail_mask](const auto _Prev, const auto _Cur, + const auto _Mask) noexcept { + return _Traits::_Blend(_Prev, _Cur, _mm256_and_si256(_Tail_mask, _Mask)); + }; + _Update_min_max(_Cur_vals, _Blend_idx_0_mask, _Blend_idx_1_mask); _Advance_bytes(_First, _Tail_byte_size); } } From cb67ee5eed5d9d81806bb5c7926ef554c25b15d9 Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Tue, 27 Aug 2024 15:18:42 +0300 Subject: [PATCH 6/8] fix floating mask --- stl/src/vector_algorithms.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 795a9af520d..655f9d7b14a 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -1484,7 +1484,7 @@ namespace { }; struct _Minmax_traits_f_avx : _Minmax_traits_f_base, _Minmax_traits_avx_base { - static constexpr size_t _Tail_mask = 0xC; + static constexpr size_t _Tail_mask = 0x1C; static __m256 _Blendval(const __m256 _Px1, const __m256 _Px2, const __m256i _Msk) noexcept { return _mm256_blendv_ps(_Px1, _Px2, _mm256_castsi256_ps(_Msk)); @@ -1652,7 +1652,7 @@ namespace { }; struct _Minmax_traits_d_avx : _Minmax_traits_d_base, _Minmax_traits_avx_base { - static constexpr size_t _Tail_mask = 0x8; + static constexpr size_t _Tail_mask = 0x18; static __m256d _Blendval(const __m256d _Px1, const __m256d _Px2, const __m256i _Msk) noexcept { return _mm256_blendv_pd(_Px1, _Px2, _mm256_castsi256_pd(_Msk)); From 735803dd89ad27e41fb807fc3658b5d8a478117e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 7 Oct 2024 14:26:46 -0700 Subject: [PATCH 7/8] Use `[[maybe_unused]]`. --- stl/src/vector_algorithms.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index 2f3445a4697..ae645777c2f 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -1812,7 +1812,7 @@ namespace { auto _Cur_idx_max = _Traits::_Zero(); // vector of vertical maximum indices auto _Cur_idx = _Traits::_Zero(); // current vector of indices - const auto _Update_min_max = [&](const auto _Cur_vals, const auto _Blend_idx_0, + const auto _Update_min_max = [&](const auto _Cur_vals, [[maybe_unused]] const auto _Blend_idx_0, const auto _Blend_idx_1) noexcept { if constexpr ((_Mode & _Mode_min) != 0) { // Looking for the first occurrence of minimum, don't overwrite with newly found occurrences @@ -1820,8 +1820,6 @@ namespace { // Remember their vertical indices _Cur_idx_min = _Blend_idx_1(_Cur_idx_min, _Cur_idx, _Traits::_Mask_cast(_Is_less)); _Cur_vals_min = _Traits::_Min(_Cur_vals_min, _Cur_vals, _Is_less); // Update the current minimum - - (void) _Blend_idx_0; } if constexpr (_Mode == _Mode_max) { @@ -1830,8 +1828,6 @@ namespace { // Remember their vertical indices _Cur_idx_max = _Blend_idx_1(_Cur_idx_max, _Cur_idx, _Traits::_Mask_cast(_Is_greater)); _Cur_vals_max = _Traits::_Max(_Cur_vals_max, _Cur_vals, _Is_greater); // Update the current maximum - - (void) _Blend_idx_0; } else if constexpr (_Mode == _Mode_both) { // Looking for the last occurrence of maximum, do overwrite with newly found occurrences const auto _Is_less = _Traits::_Cmp_gt(_Cur_vals_max, _Cur_vals); // !(_Cur_vals >= _Cur_vals_max) From b709699531db2d68de541c0adcab121029e405f5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 7 Oct 2024 14:50:42 -0700 Subject: [PATCH 8/8] Advance when `_Tail_byte_size` is non-zero. --- stl/src/vector_algorithms.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/src/vector_algorithms.cpp b/stl/src/vector_algorithms.cpp index ae645777c2f..f786761bb5b 100644 --- a/stl/src/vector_algorithms.cpp +++ b/stl/src/vector_algorithms.cpp @@ -2137,9 +2137,9 @@ namespace { _Tail_vals = _Traits::_Blendval(_Cur_vals, _Tail_vals, _Tail_mask); _Update_min_max(_Tail_vals); - } - _Advance_bytes(_First, _Tail_byte_size); + _Advance_bytes(_First, _Tail_byte_size); + } } // Reached end. Compute horizontal min and/or max.