Added a SIMD helper for the "floating index to sample index + interpolation coefficients"
This commit is contained in:
parent
9324d137bc
commit
ced4178643
6 changed files with 200 additions and 8 deletions
93
benchmarks/BM_interpolationCast.cpp
Normal file
93
benchmarks/BM_interpolationCast.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2019, Paul Ferrand
|
||||
// All rights reserved.
|
||||
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <numeric>
|
||||
#include <absl/algorithm/container.h>
|
||||
#include "../sfizz/SIMDHelpers.h"
|
||||
|
||||
// In this one we have an array of jumps
|
||||
|
||||
constexpr float maxJump { 4 };
|
||||
|
||||
class InterpolationCast : public benchmark::Fixture {
|
||||
public:
|
||||
void SetUp(const ::benchmark::State& state) {
|
||||
std::random_device rd { };
|
||||
std::mt19937 gen { rd() };
|
||||
std::uniform_real_distribution<float> dist { 0, maxJump };
|
||||
jumps = std::vector<int>(state.range(0));
|
||||
leftCoeffs = std::vector<float>(state.range(0));
|
||||
rightCoeffs = std::vector<float>(state.range(0));
|
||||
floatJumps = std::vector<float>(state.range(0));
|
||||
absl::c_generate(floatJumps, [&]() { return dist(gen); });
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& state [[maybe_unused]]) {
|
||||
|
||||
}
|
||||
|
||||
std::vector<int> jumps;
|
||||
std::vector<float> leftCoeffs;
|
||||
std::vector<float> rightCoeffs;
|
||||
std::vector<float> floatJumps;
|
||||
};
|
||||
|
||||
|
||||
BENCHMARK_DEFINE_F(InterpolationCast, Scalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfzInterpolationCast<float, false>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(InterpolationCast, SIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfzInterpolationCast<float, true>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(InterpolationCast, Scalar_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfzInterpolationCast<float, false>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(InterpolationCast, SIMD_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfzInterpolationCast<float, true>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Register the function as a benchmark
|
||||
BENCHMARK_REGISTER_F(InterpolationCast, Scalar)->RangeMultiplier(2)->Range((2<<6), (2<<12));
|
||||
BENCHMARK_REGISTER_F(InterpolationCast, SIMD)->RangeMultiplier(2)->Range((2<<6), (2<<12));
|
||||
BENCHMARK_REGISTER_F(InterpolationCast, Scalar_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12));
|
||||
BENCHMARK_REGISTER_F(InterpolationCast, SIMD_Unaligned)->RangeMultiplier(2)->Range((2<<6), (2<<12));
|
||||
BENCHMARK_MAIN();
|
||||
|
|
@ -78,6 +78,9 @@ target_link_libraries(bm_meanSquared benchmark absl::span absl::algorithm)
|
|||
add_executable(bm_cumsum BM_cumsum.cpp ${SFIZZ_SIMD_SOURCES})
|
||||
target_link_libraries(bm_cumsum benchmark absl::span absl::algorithm)
|
||||
|
||||
add_executable(bm_interpolationCast BM_interpolationCast.cpp ${SFIZZ_SIMD_SOURCES})
|
||||
target_link_libraries(bm_interpolationCast benchmark absl::span absl::algorithm)
|
||||
|
||||
add_custom_target(sfizz_benchmarks)
|
||||
add_dependencies(sfizz_benchmarks
|
||||
bm_opf_high_vs_low
|
||||
|
|
@ -87,6 +90,7 @@ add_dependencies(sfizz_benchmarks
|
|||
bm_meanSquared
|
||||
bm_fill
|
||||
bm_cumsum
|
||||
bm_interpolationCast
|
||||
bm_mathfuns
|
||||
bm_gain
|
||||
bm_looping
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ namespace SIMDConfig {
|
|||
constexpr bool copy { false };
|
||||
constexpr bool pan { true };
|
||||
constexpr bool cumsum { true };
|
||||
constexpr bool sfzInterpolationCast { true };
|
||||
constexpr bool mean { false };
|
||||
constexpr bool meanSquared { false };
|
||||
}
|
||||
|
|
@ -155,3 +155,9 @@ void cumsum<float, true>(absl::Span<const float> input, absl::Span<float> output
|
|||
{
|
||||
cumsum<float, false>(input, output);
|
||||
}
|
||||
|
||||
template<>
|
||||
void sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept
|
||||
{
|
||||
sfzInterpolationCast<float, false>(floatJumps, jumps, leftCoeffs, rightCoeffs);
|
||||
}
|
||||
|
|
@ -494,3 +494,35 @@ void cumsum(absl::Span<const float> input, absl::Span<float> output) noexcept
|
|||
|
||||
template <>
|
||||
void cumsum<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept;
|
||||
|
||||
template<class T>
|
||||
void snippetSFZInterpolationCast(const T*& floatJump, int*& jump, T*& leftCoeff, T*& rightCoeff)
|
||||
{
|
||||
*jump = static_cast<int>(*floatJump);
|
||||
*rightCoeff = *floatJump - static_cast<float>(*jump);
|
||||
*leftCoeff = static_cast<T>(1.0) - *rightCoeff;
|
||||
leftCoeff++;
|
||||
jump++;
|
||||
rightCoeff++;
|
||||
floatJump++;
|
||||
}
|
||||
|
||||
template<class T, bool SIMD = SIMDConfig::sfzInterpolationCast>
|
||||
void sfzInterpolationCast(absl::Span<const T> floatJumps, absl::Span<int> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs) noexcept
|
||||
{
|
||||
ASSERT(jumps.size() >= floatJumps.size());
|
||||
ASSERT(jumps.size() == leftCoeffs.size());
|
||||
ASSERT(jumps.size() == rightCoeffs.size());
|
||||
|
||||
auto floatJump = floatJumps.data();
|
||||
auto jump = jumps.data();
|
||||
auto leftCoeff = leftCoeffs.data();
|
||||
auto rightCoeff = rightCoeffs.data();
|
||||
const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), leftCoeffs.size(), rightCoeffs.size());
|
||||
|
||||
while (floatJump < sentinel)
|
||||
snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff);
|
||||
}
|
||||
|
||||
template<>
|
||||
void sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept;
|
||||
|
|
@ -522,6 +522,26 @@ void add<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
|||
snippetAdd<float>(in, out);
|
||||
}
|
||||
|
||||
template <>
|
||||
void add<float, true>(float value, absl::Span<float> output) noexcept
|
||||
{
|
||||
auto* out = output.begin();
|
||||
auto* sentinel = output.end();
|
||||
const auto* lastAligned = prevAligned(sentinel);
|
||||
|
||||
while (unaligned(out) && out < lastAligned)
|
||||
snippetAdd<float>(value, out);
|
||||
|
||||
auto mmValue = _mm_set_ps1(value);
|
||||
while (out < lastAligned) {
|
||||
_mm_store_ps(out, _mm_add_ps(mmValue, _mm_load_ps(out)));
|
||||
out += TypeAlignment;
|
||||
}
|
||||
|
||||
while (out < sentinel)
|
||||
snippetAdd<float>(value, out);
|
||||
}
|
||||
|
||||
template <>
|
||||
void subtract<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
||||
{
|
||||
|
|
@ -582,8 +602,8 @@ void pan<float, true>(absl::Span<const float> panEnvelope, absl::Span<float> lef
|
|||
|
||||
const auto mmOne = _mm_set_ps1(1.0f);
|
||||
const auto mmPiFour = _mm_set_ps1(piFour<float>);
|
||||
__m128 mmCos;
|
||||
__m128 mmSin;
|
||||
__m128 mmCos;
|
||||
__m128 mmSin;
|
||||
while (pan < lastAligned) {
|
||||
auto mmPan = _mm_load_ps(pan);
|
||||
mmPan = _mm_add_ps(mmOne, mmPan);
|
||||
|
|
@ -615,9 +635,9 @@ float mean<float, true>(absl::Span<const float> vector) noexcept
|
|||
|
||||
while (unaligned(value) && value < lastAligned)
|
||||
result += *value++;
|
||||
|
||||
|
||||
auto mmSums = _mm_setzero_ps();
|
||||
while(value < lastAligned) {
|
||||
while (value < lastAligned) {
|
||||
mmSums = _mm_add_ps(mmSums, _mm_load_ps(value));
|
||||
value += TypeAlignment;
|
||||
}
|
||||
|
|
@ -625,7 +645,7 @@ float mean<float, true>(absl::Span<const float> vector) noexcept
|
|||
std::array<float, 4> sseResult;
|
||||
_mm_store_ps(sseResult.data(), mmSums);
|
||||
|
||||
for (auto sseValue: sseResult)
|
||||
for (auto sseValue : sseResult)
|
||||
result += sseValue;
|
||||
|
||||
while (value < sentinel)
|
||||
|
|
@ -649,9 +669,9 @@ float meanSquared<float, true>(absl::Span<const float> vector) noexcept
|
|||
result += (*value) * (*value);
|
||||
value++;
|
||||
}
|
||||
|
||||
|
||||
auto mmSums = _mm_setzero_ps();
|
||||
while(value < lastAligned) {
|
||||
while (value < lastAligned) {
|
||||
const auto mmValues = _mm_load_ps(value);
|
||||
mmSums = _mm_add_ps(mmSums, _mm_mul_ps(mmValues, mmValues));
|
||||
value += TypeAlignment;
|
||||
|
|
@ -660,7 +680,7 @@ float meanSquared<float, true>(absl::Span<const float> vector) noexcept
|
|||
std::array<float, 4> sseResult;
|
||||
_mm_store_ps(sseResult.data(), mmSums);
|
||||
|
||||
for (auto sseValue: sseResult)
|
||||
for (auto sseValue : sseResult)
|
||||
result += sseValue;
|
||||
|
||||
while (value < sentinel) {
|
||||
|
|
@ -702,3 +722,39 @@ void cumsum<float, true>(absl::Span<const float> input, absl::Span<float> output
|
|||
while (in < sentinel)
|
||||
snippetCumsum(in, out);
|
||||
}
|
||||
|
||||
template <>
|
||||
void sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept
|
||||
{
|
||||
ASSERT(jumps.size() >= floatJumps.size());
|
||||
ASSERT(jumps.size() == leftCoeffs.size());
|
||||
ASSERT(jumps.size() == rightCoeffs.size());
|
||||
|
||||
auto floatJump = floatJumps.data();
|
||||
auto jump = jumps.data();
|
||||
auto leftCoeff = leftCoeffs.data();
|
||||
auto rightCoeff = rightCoeffs.data();
|
||||
const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), leftCoeffs.size(), rightCoeffs.size());
|
||||
const auto lastAligned = prevAligned(sentinel);
|
||||
|
||||
while (unaligned(floatJump, reinterpret_cast<float*>(jump), leftCoeff, rightCoeff) && floatJump < lastAligned)
|
||||
snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff);
|
||||
|
||||
while (floatJump < lastAligned) {
|
||||
auto mmFloatJumps = _mm_load_ps(floatJump);
|
||||
auto mmIndices = _mm_cvtps_epi32(_mm_sub_ps(mmFloatJumps, _mm_set_ps1(0.4999999552965164184570312f)));
|
||||
_mm_store_si128(reinterpret_cast<__m128i*>(jump), mmIndices);
|
||||
|
||||
auto mmRight = _mm_sub_ps(mmFloatJumps, _mm_cvtepi32_ps(mmIndices));
|
||||
auto mmLeft = _mm_sub_ps(_mm_set_ps1(1.0f), mmRight);
|
||||
_mm_store_ps(leftCoeff, mmLeft);
|
||||
_mm_store_ps(rightCoeff, mmRight);
|
||||
floatJump += TypeAlignment;
|
||||
jump += TypeAlignment;
|
||||
leftCoeff += TypeAlignment;
|
||||
rightCoeff += TypeAlignment;
|
||||
}
|
||||
|
||||
while(floatJump < sentinel)
|
||||
snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue