Updated the math functions for better alignment handling
This commit is contained in:
parent
04181f0d10
commit
0e89a0b2c6
2 changed files with 165 additions and 147 deletions
|
|
@ -1,14 +1,16 @@
|
||||||
|
#include "../sources/SIMDHelpers.h"
|
||||||
|
#include "absl/types/span.h"
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
#include <random>
|
|
||||||
#include <numeric>
|
|
||||||
#include <vector>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "../sources/SIMDHelpers.h"
|
#include <numeric>
|
||||||
|
#include <random>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
class MyFixture : public benchmark::Fixture {
|
class MyFixture : public benchmark::Fixture {
|
||||||
public:
|
public:
|
||||||
void SetUp(const ::benchmark::State& state) {
|
void SetUp(const ::benchmark::State& state)
|
||||||
|
{
|
||||||
std::random_device rd {};
|
std::random_device rd {};
|
||||||
std::mt19937 gen { rd() };
|
std::mt19937 gen { rd() };
|
||||||
std::uniform_real_distribution<float> dist { 0.1, 1 };
|
std::uniform_real_distribution<float> dist { 0.1, 1 };
|
||||||
|
|
@ -17,134 +19,123 @@ public:
|
||||||
std::generate(source.begin(), source.end(), [&]() { return dist(gen); });
|
std::generate(source.begin(), source.end(), [&]() { return dist(gen); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void TearDown(const ::benchmark::State& state [[maybe_unused]]) {
|
void TearDown(const ::benchmark::State& state [[maybe_unused]])
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> source;
|
std::vector<float> source;
|
||||||
std::vector<float> result;
|
std::vector<float> result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(MyFixture, Dummy)
|
||||||
BENCHMARK_DEFINE_F(MyFixture, Dummy)(benchmark::State& state) {
|
(benchmark::State& state)
|
||||||
for (auto _ : state)
|
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
for (int i = 0; i < state.range(0); ++i)
|
for (int i = 0; i < state.range(0); ++i)
|
||||||
result[i] = source[i];
|
result[i] = source[i];
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, StdExp)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, ScalarExp)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
|
||||||
for (int i = 0; i < state.range(0); ++i)
|
|
||||||
result[i] = std::exp(source[i]);
|
|
||||||
benchmark::DoNotOptimize(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, ScalarExp)(benchmark::State& state) {
|
|
||||||
for (auto _ : state)
|
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
exp<float, false>(source, absl::MakeSpan(result));
|
exp<float, false>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, SIMDExp)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, SIMDExp)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
exp<float, true>(source, absl::MakeSpan(result));
|
exp<float, true>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, StdLog)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, ScalarExp_Unaligned)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < state.range(0); ++i)
|
for (auto _ : state) {
|
||||||
result[i] = std::log(source[i]);
|
exp<float, false>(absl::MakeSpan(source).subspan(1), absl::MakeSpan(result).subspan(1));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, ScalarLog)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, SIMDExp_Unaligned)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
|
exp<float, true>(absl::MakeSpan(source).subspan(1), absl::MakeSpan(result).subspan(1));
|
||||||
|
benchmark::DoNotOptimize(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK_DEFINE_F(MyFixture, ScalarLog)
|
||||||
|
(benchmark::State& state)
|
||||||
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
log<float, false>(source, absl::MakeSpan(result));
|
log<float, false>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, SIMDLog)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, SIMDLog)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
log<float, true>(source, absl::MakeSpan(result));
|
log<float, true>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, StdSin)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, ScalarSin)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
|
||||||
for (int i = 0; i < state.range(0); ++i)
|
|
||||||
result[i] = std::sin(source[i]);
|
|
||||||
benchmark::DoNotOptimize(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, ScalarSin)(benchmark::State& state) {
|
|
||||||
for (auto _ : state)
|
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
sin<float, false>(source, absl::MakeSpan(result));
|
sin<float, false>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, SIMDSin)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, SIMDSin)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
sin<float, true>(source, absl::MakeSpan(result));
|
sin<float, true>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, StdCos)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, ScalarCos)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
|
||||||
for (int i = 0; i < state.range(0); ++i)
|
|
||||||
result[i] = std::cos(source[i]);
|
|
||||||
benchmark::DoNotOptimize(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, ScalarCos)(benchmark::State& state) {
|
|
||||||
for (auto _ : state)
|
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
cos<float, false>(source, absl::MakeSpan(result));
|
cos<float, false>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(MyFixture, SIMDCos)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(MyFixture, SIMDCos)
|
||||||
for (auto _ : state)
|
(benchmark::State& state)
|
||||||
{
|
{
|
||||||
|
for (auto _ : state) {
|
||||||
cos<float, true>(source, absl::MakeSpan(result));
|
cos<float, true>(source, absl::MakeSpan(result));
|
||||||
benchmark::DoNotOptimize(result);
|
benchmark::DoNotOptimize(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_REGISTER_F(MyFixture, Dummy)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, Dummy)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, StdExp)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
|
||||||
BENCHMARK_REGISTER_F(MyFixture, ScalarExp)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, ScalarExp)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, SIMDExp)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, SIMDExp)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, StdLog)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, ScalarExp_Unaligned)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
|
BENCHMARK_REGISTER_F(MyFixture, SIMDExp_Unaligned)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, ScalarLog)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, ScalarLog)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, SIMDLog)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, SIMDLog)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, StdSin)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
|
||||||
BENCHMARK_REGISTER_F(MyFixture, ScalarSin)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, ScalarSin)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, SIMDSin)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, SIMDSin)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, StdCos)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
|
||||||
BENCHMARK_REGISTER_F(MyFixture, ScalarCos)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, ScalarCos)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
BENCHMARK_REGISTER_F(MyFixture, SIMDCos)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
BENCHMARK_REGISTER_F(MyFixture, SIMDCos)->RangeMultiplier(4)->Range(1 << 6, 1 << 10);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "SIMDHelpers.h"
|
|
||||||
#include "Helpers.h"
|
#include "Helpers.h"
|
||||||
|
#include "SIMDHelpers.h"
|
||||||
|
|
||||||
#if HAVE_X86INTRIN_H
|
#if HAVE_X86INTRIN_H
|
||||||
#include <x86intrin.h>
|
#include <x86intrin.h>
|
||||||
|
|
@ -17,8 +17,10 @@ using Type = float;
|
||||||
[[maybe_unused]] constexpr uintptr_t ByteAlignment { TypeAlignment * sizeof(Type) };
|
[[maybe_unused]] constexpr uintptr_t ByteAlignment { TypeAlignment * sizeof(Type) };
|
||||||
[[maybe_unused]] constexpr uintptr_t ByteAlignmentMask { ByteAlignment - 1 };
|
[[maybe_unused]] constexpr uintptr_t ByteAlignmentMask { ByteAlignment - 1 };
|
||||||
|
|
||||||
|
struct AlignmentSentinels {
|
||||||
struct AlignmentSentinels { float* nextAligned; float* lastAligned; };
|
float* nextAligned;
|
||||||
|
float* lastAligned;
|
||||||
|
};
|
||||||
|
|
||||||
float* nextAligned(const float* ptr)
|
float* nextAligned(const float* ptr)
|
||||||
{
|
{
|
||||||
|
|
@ -69,8 +71,7 @@ void readInterleaved<float, true>(absl::Span<const float> input, absl::Span<floa
|
||||||
while (unaligned(in, lOut, rOut) && in < lastAligned)
|
while (unaligned(in, lOut, rOut) && in < lastAligned)
|
||||||
snippetRead<float>(in, lOut, rOut);
|
snippetRead<float>(in, lOut, rOut);
|
||||||
|
|
||||||
while (in < lastAligned )
|
while (in < lastAligned) {
|
||||||
{
|
|
||||||
auto register0 = _mm_load_ps(in);
|
auto register0 = _mm_load_ps(in);
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
auto register1 = _mm_load_ps(in);
|
auto register1 = _mm_load_ps(in);
|
||||||
|
|
@ -108,8 +109,7 @@ void writeInterleaved<float, true>(absl::Span<const float> inputLeft, absl::Span
|
||||||
while (unaligned(out, rIn, lIn) && out < lastAligned)
|
while (unaligned(out, rIn, lIn) && out < lastAligned)
|
||||||
snippetWrite<float>(out, lIn, rIn);
|
snippetWrite<float>(out, lIn, rIn);
|
||||||
|
|
||||||
while (out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
const auto lInRegister = _mm_load_ps(lIn);
|
const auto lInRegister = _mm_load_ps(lIn);
|
||||||
const auto rInRegister = _mm_load_ps(rIn);
|
const auto rInRegister = _mm_load_ps(rIn);
|
||||||
|
|
||||||
|
|
@ -129,7 +129,6 @@ void writeInterleaved<float, true>(absl::Span<const float> inputLeft, absl::Span
|
||||||
snippetWrite<float>(out, lIn, rIn);
|
snippetWrite<float>(out, lIn, rIn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fill<float, true>(absl::Span<float> output, float value) noexcept
|
void fill<float, true>(absl::Span<float> output, float value) noexcept
|
||||||
{
|
{
|
||||||
|
|
@ -157,12 +156,19 @@ void exp<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
||||||
auto* in = input.begin();
|
auto* in = input.begin();
|
||||||
auto* out = output.begin();
|
auto* out = output.begin();
|
||||||
auto* sentinel = in + std::min(input.size(), output.size());
|
auto* sentinel = in + std::min(input.size(), output.size());
|
||||||
while (in < sentinel)
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
{
|
|
||||||
_mm_storeu_ps(out, exp_ps(_mm_loadu_ps(in)));
|
while (unaligned(in, out) && in < lastAligned)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
|
|
||||||
|
while (in < lastAligned) {
|
||||||
|
_mm_store_ps(out, exp_ps(_mm_load_ps(in)));
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (in < sentinel)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -172,12 +178,19 @@ void cos<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
||||||
auto* in = input.begin();
|
auto* in = input.begin();
|
||||||
auto* out = output.begin();
|
auto* out = output.begin();
|
||||||
auto* sentinel = in + std::min(input.size(), output.size());
|
auto* sentinel = in + std::min(input.size(), output.size());
|
||||||
while (in < sentinel)
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
{
|
|
||||||
_mm_storeu_ps(out, cos_ps(_mm_loadu_ps(in)));
|
while (unaligned(in, out) && in < lastAligned)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
|
|
||||||
|
while (in < lastAligned) {
|
||||||
|
_mm_store_ps(out, cos_ps(_mm_load_ps(in)));
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (in < sentinel)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -187,12 +200,19 @@ void log<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
||||||
auto* in = input.begin();
|
auto* in = input.begin();
|
||||||
auto* out = output.begin();
|
auto* out = output.begin();
|
||||||
auto* sentinel = in + std::min(input.size(), output.size());
|
auto* sentinel = in + std::min(input.size(), output.size());
|
||||||
while (in < sentinel)
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
{
|
|
||||||
_mm_storeu_ps(out, log_ps(_mm_loadu_ps(in)));
|
while (unaligned(in, out) && in < lastAligned)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
|
|
||||||
|
while (in < lastAligned) {
|
||||||
|
_mm_store_ps(out, log_ps(_mm_load_ps(in)));
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (in < sentinel)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -202,12 +222,19 @@ void sin<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
||||||
auto* in = input.begin();
|
auto* in = input.begin();
|
||||||
auto* out = output.begin();
|
auto* out = output.begin();
|
||||||
auto* sentinel = in + std::min(input.size(), output.size());
|
auto* sentinel = in + std::min(input.size(), output.size());
|
||||||
while (in < sentinel)
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
{
|
|
||||||
_mm_storeu_ps(out, sin_ps(_mm_loadu_ps(in)));
|
while (unaligned(in, out) && in < lastAligned)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
|
|
||||||
|
while (in < lastAligned) {
|
||||||
|
_mm_store_ps(out, sin_ps(_mm_load_ps(in)));
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (in < sentinel)
|
||||||
|
*out++ = std::exp(*in++);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|
@ -222,8 +249,7 @@ void applyGain<float, true>(float gain, absl::Span<const float> input, absl::Spa
|
||||||
while (unaligned(out, in) && out < lastAligned)
|
while (unaligned(out, in) && out < lastAligned)
|
||||||
*out++ = gain * (*in++);
|
*out++ = gain * (*in++);
|
||||||
|
|
||||||
while (out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
_mm_store_ps(out, _mm_mul_ps(mmGain, _mm_load_ps(in)));
|
_mm_store_ps(out, _mm_mul_ps(mmGain, _mm_load_ps(in)));
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
|
|
@ -245,8 +271,7 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
|
||||||
while (unaligned(out, in, g) && out < lastAligned)
|
while (unaligned(out, in, g) && out < lastAligned)
|
||||||
snippetGainSpan<float>(g, in, out);
|
snippetGainSpan<float>(g, in, out);
|
||||||
|
|
||||||
while (out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
_mm_store_ps(out, _mm_mul_ps(_mm_load_ps(g), _mm_load_ps(in)));
|
_mm_store_ps(out, _mm_mul_ps(_mm_load_ps(g), _mm_load_ps(in)));
|
||||||
g += TypeAlignment;
|
g += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
|
|
@ -258,7 +283,13 @@ void applyGain<float, true>(absl::Span<const float> gain, absl::Span<const float
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs, absl::Span<int> indices, float floatIndex, float loopEnd, float loopStart) noexcept
|
void loopingSFZIndex<float, true>( absl::Span<const float> jumps,
|
||||||
|
absl::Span<float> leftCoeffs,
|
||||||
|
absl::Span<float> rightCoeffs,
|
||||||
|
absl::Span<int> indices,
|
||||||
|
float floatIndex,
|
||||||
|
float loopEnd,
|
||||||
|
float loopStart) noexcept
|
||||||
{
|
{
|
||||||
ASSERT(indices.size() >= jumps.size());
|
ASSERT(indices.size() >= jumps.size());
|
||||||
ASSERT(indices.size() == leftCoeffs.size());
|
ASSERT(indices.size() == leftCoeffs.size());
|
||||||
|
|
@ -278,8 +309,7 @@ void loopingSFZIndex<float, true>(absl::Span<const float> jumps, absl::Span<floa
|
||||||
auto mmFloatIndex = _mm_set_ps1(floatIndex);
|
auto mmFloatIndex = _mm_set_ps1(floatIndex);
|
||||||
const auto mmJumpBack = _mm_set1_ps(loopEnd - loopStart);
|
const auto mmJumpBack = _mm_set1_ps(loopEnd - loopStart);
|
||||||
const auto mmLoopEnd = _mm_set1_ps(loopEnd);
|
const auto mmLoopEnd = _mm_set1_ps(loopEnd);
|
||||||
while (jump < alignedEnd)
|
while (jump < alignedEnd) {
|
||||||
{
|
|
||||||
auto mmOffset = _mm_load_ps(jump);
|
auto mmOffset = _mm_load_ps(jump);
|
||||||
mmOffset = _mm_add_ps(mmOffset, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOffset), 4)));
|
mmOffset = _mm_add_ps(mmOffset, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOffset), 4)));
|
||||||
mmOffset = _mm_add_ps(mmOffset, _mm_shuffle_ps(_mm_setzero_ps(), mmOffset, 0x40));
|
mmOffset = _mm_add_ps(mmOffset, _mm_shuffle_ps(_mm_setzero_ps(), mmOffset, 0x40));
|
||||||
|
|
@ -325,8 +355,7 @@ float linearRamp<float, true>(absl::Span<float> output, float value, float step)
|
||||||
auto mmValue = _mm_set1_ps(value);
|
auto mmValue = _mm_set1_ps(value);
|
||||||
auto mmStep = _mm_set_ps(step + step + step + step, step + step + step, step + step, step);
|
auto mmStep = _mm_set_ps(step + step + step + step, step + step + step, step + step, step);
|
||||||
|
|
||||||
while (out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
mmValue = _mm_add_ps(mmValue, mmStep);
|
mmValue = _mm_add_ps(mmValue, mmStep);
|
||||||
_mm_store_ps(out, mmValue);
|
_mm_store_ps(out, mmValue);
|
||||||
mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3));
|
mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3));
|
||||||
|
|
@ -351,8 +380,7 @@ float multiplicativeRamp<float, true>(absl::Span<float> output, float value, flo
|
||||||
auto mmValue = _mm_set1_ps(value);
|
auto mmValue = _mm_set1_ps(value);
|
||||||
auto mmStep = _mm_set_ps(step * step * step * step, step * step * step, step * step, step);
|
auto mmStep = _mm_set_ps(step * step * step * step, step * step * step, step * step, step);
|
||||||
|
|
||||||
while (out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
mmValue = _mm_mul_ps(mmValue, mmStep);
|
mmValue = _mm_mul_ps(mmValue, mmStep);
|
||||||
_mm_store_ps(out, mmValue);
|
_mm_store_ps(out, mmValue);
|
||||||
mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3));
|
mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3));
|
||||||
|
|
@ -377,8 +405,7 @@ void add<float, true>(absl::Span<const float> input, absl::Span<float> output) n
|
||||||
while (unaligned(in, out) && out < lastAligned)
|
while (unaligned(in, out) && out < lastAligned)
|
||||||
snippetAdd<float>(in, out);
|
snippetAdd<float>(in, out);
|
||||||
|
|
||||||
while(out < lastAligned)
|
while (out < lastAligned) {
|
||||||
{
|
|
||||||
_mm_store_ps(out, _mm_add_ps(_mm_load_ps(in), _mm_load_ps(out)));
|
_mm_store_ps(out, _mm_add_ps(_mm_load_ps(in), _mm_load_ps(out)));
|
||||||
out += TypeAlignment;
|
out += TypeAlignment;
|
||||||
in += TypeAlignment;
|
in += TypeAlignment;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue