From d1e6f9a02a5b4f070cd9ea7c2951bdae669e7fab Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 10 Aug 2019 13:53:17 +0200 Subject: [PATCH] Better index loader --- CMakeLists.txt | 4 ++ benchmarks/Looping_index_2.cpp | 123 +++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 benchmarks/Looping_index_2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4cdffe37..a5a00501 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,3 +176,7 @@ target_link_libraries(bench_opf_high_vs_low benchmark gsl::gsl-lite) add_executable(bench_looping_index benchmarks/Looping_index.cpp) # Per OS properties target_link_libraries(bench_looping_index benchmark) + +add_executable(bench_looping_index_2 benchmarks/Looping_index_2.cpp) +# Per OS properties +target_link_libraries(bench_looping_index_2 benchmark) diff --git a/benchmarks/Looping_index_2.cpp b/benchmarks/Looping_index_2.cpp new file mode 100644 index 00000000..69b39c3f --- /dev/null +++ b/benchmarks/Looping_index_2.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include "../sources/Intrinsics.h" +#include "../sources/Buffer.h" + +// In this one we have an array of indices + +constexpr int loopOffset { 5 }; +constexpr int loopPoint { 51 }; +constexpr int loopBack { loopPoint - loopOffset }; +constexpr float maxJump { 4 }; + +static void Straight(benchmark::State& state) { + Buffer indices(state.range(0)); + Buffer leftCoeffs(state.range(0)); + Buffer rightCoeffs(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 0, maxJump }; + Buffer jumps(state.range(0)); + std::generate(jumps.begin(), jumps.end(), [&]() { return dist(gen); }); + + for (auto _ : state) + { + float floatingIndex = 0.0f; + auto index = indices.data(); + auto leftCoeff = leftCoeffs.data(); + auto rightCoeff = rightCoeffs.data(); + auto jump = jumps.data(); + + while (index < indices.end()) + { + *index = static_cast(floatingIndex); + *rightCoeff = floatingIndex - *index; + *leftCoeff = 1.0f - *rightCoeff; + floatingIndex += *jump; + if (floatingIndex > loopPoint) + floatingIndex -= loopBack; + index++; + leftCoeff++; + rightCoeff++; + jump++; + } + } +} + +static void SIMD(benchmark::State& state) { + Buffer indices(state.range(0)); + Buffer leftCoeffs(state.range(0)); + Buffer rightCoeffs(state.range(0)); + + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 0, maxJump }; + Buffer jumps(state.range(0)); + std::generate(jumps.begin(), jumps.end(), [&]() { return dist(gen); }); + + for (auto _ : state) + { + auto index = indices.data(); + auto leftCoeff = leftCoeffs.data(); + auto rightCoeff = rightCoeffs.data(); + auto jump = jumps.data(); + + const auto alignedEnd = state.range(0) - (state.range(0) & 3); + + auto floatingIndexReg = _mm_set_ps1(48.0f); + const auto wrappingReg = _mm_set1_ps(loopBack); + const auto upperBoundReg = _mm_set1_ps(loopPoint); + + while (index < indices.data() + alignedEnd) + { + auto offsetReg = _mm_load_ps(jump); + offsetReg = _mm_add_ps(offsetReg, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(offsetReg), 4))); + offsetReg = _mm_add_ps(offsetReg, _mm_shuffle_ps(_mm_setzero_ps(), offsetReg, 0x40)); + + floatingIndexReg = _mm_add_ps(floatingIndexReg, offsetReg); + const auto comparisonReg = _mm_cmpge_ps(floatingIndexReg, upperBoundReg); + auto loopbackReg = _mm_sub_ps(floatingIndexReg, wrappingReg); + loopbackReg = _mm_and_ps(comparisonReg, loopbackReg); + floatingIndexReg = _mm_andnot_ps(comparisonReg, floatingIndexReg); + floatingIndexReg = _mm_add_ps(floatingIndexReg, loopbackReg); + + auto indexReg = _mm_cvtps_epi32(_mm_sub_ps(floatingIndexReg, _mm_set_ps1(0.5f))); + _mm_store_si128(reinterpret_cast<__m128i*>(index), indexReg); + + auto rightCoefficientsReg = _mm_sub_ps(floatingIndexReg, _mm_cvtepi32_ps(indexReg)); + auto leftCoefficientsReg = _mm_sub_ps(_mm_set_ps1(1.0f), rightCoefficientsReg); + _mm_store_ps(leftCoeff, leftCoefficientsReg); + _mm_store_ps(rightCoeff, rightCoefficientsReg); + + floatingIndexReg = _mm_shuffle_ps(floatingIndexReg, floatingIndexReg, _MM_SHUFFLE(3, 3, 3, 3)); + // floatingIndex = _mm_cvtss_f32(_mm_shuffle_ps(floatingIndexReg, floatingIndexReg, _MM_SHUFFLE(0, 0, 0, 3)));; + // floatingIndex = *(index + 3) + *(rightCoeff + 3); + index += 4; + jump += 4; + leftCoeff += 4; + rightCoeff += 4; + } + + float floatingIndex = _mm_cvtss_f32(floatingIndexReg); + while (index < indices.end()) + { + *index = static_cast(floatingIndex); + *rightCoeff = floatingIndex - *index; + *leftCoeff = 1.0f - *rightCoeff; + floatingIndex += *jump; + if (floatingIndex > loopPoint) + floatingIndex -= loopBack; + index++; + leftCoeff++; + rightCoeff++; + jump++; + } + } +} + +// Register the function as a benchmark +BENCHMARK(Straight)->RangeMultiplier(2)->Range((2<<6), (2<<12)); +BENCHMARK(SIMD)->RangeMultiplier(2)->Range((2<<6), (2<<12)); +BENCHMARK_MAIN(); \ No newline at end of file