Better index loader

This commit is contained in:
paul 2019-08-10 13:53:17 +02:00
parent e22d1673db
commit d1e6f9a02a
2 changed files with 127 additions and 0 deletions

View file

@ -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)

View file

@ -0,0 +1,123 @@
#include <benchmark/benchmark.h>
#include <vector>
#include <random>
#include <numeric>
#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<int> indices(state.range(0));
Buffer<float> leftCoeffs(state.range(0));
Buffer<float> rightCoeffs(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 0, maxJump };
Buffer<float> 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<int>(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<int> indices(state.range(0));
Buffer<float> leftCoeffs(state.range(0));
Buffer<float> rightCoeffs(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 0, maxJump };
Buffer<float> 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<int>(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();