diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e0fecf5..9d883c58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,11 +147,6 @@ add_executable(bench_opf_high_vs_low benchmarks/OPF_high_vs_low.cpp) target_link_libraries(bench_opf_high_vs_low benchmark absl::span) ############################### -add_executable(bm_cum_prod benchmarks/Cum_Prod.cpp) -target_link_libraries(bm_cum_prod benchmark) - -add_executable(bm_cum_sum benchmarks/Cum_Sum.cpp) -target_link_libraries(bm_cum_sum benchmark) add_executable(bm_write benchmarks/BM_writeInterleaved.cpp sources/SIMDSSE.cpp) target_link_libraries(bm_write benchmark absl::span) @@ -164,12 +159,12 @@ target_link_libraries(bm_fill benchmark absl::span) add_executable(bm_mathfuns benchmarks/BM_mathfuns.cpp sources/SIMDSSE.cpp) target_link_libraries(bm_mathfuns benchmark absl::span) -if (UNIX) - # target_compile_options(bm_math_loops PRIVATE -fopenmp) -endif() add_executable(bm_gain benchmarks/BM_gain.cpp sources/SIMDSSE.cpp) target_link_libraries(bm_gain benchmark absl::span) add_executable(bm_looping benchmarks/BM_looping.cpp sources/SIMDSSE.cpp) -target_link_libraries(bm_looping benchmark absl::span absl::algorithm) \ No newline at end of file +target_link_libraries(bm_looping benchmark absl::span absl::algorithm) + +add_executable(bm_ramp benchmarks/BM_ramp.cpp sources/SIMDSSE.cpp) +target_link_libraries(bm_ramp benchmark absl::span absl::algorithm) \ No newline at end of file diff --git a/benchmarks/BM_fill.cpp b/benchmarks/BM_fill.cpp index 72c5c1ea..0f780d30 100644 --- a/benchmarks/BM_fill.cpp +++ b/benchmarks/BM_fill.cpp @@ -16,7 +16,7 @@ static void Dummy(benchmark::State& state) { } } -static void Fill_float(benchmark::State& state) { +static void FillScalar(benchmark::State& state) { Buffer buffer (state.range(0)); std::random_device rd { }; std::mt19937 gen { rd() }; @@ -26,7 +26,7 @@ static void Fill_float(benchmark::State& state) { } } -static void Fill_float_unaligned(benchmark::State& state) { +static void FillScalar_unaligned(benchmark::State& state) { Buffer buffer (state.range(0)); std::random_device rd { }; std::mt19937 gen { rd() }; @@ -36,7 +36,7 @@ static void Fill_float_unaligned(benchmark::State& state) { } } -static void Fill_float_SSE(benchmark::State& state) { +static void FillSIMD(benchmark::State& state) { Buffer buffer (state.range(0)); std::random_device rd { }; std::mt19937 gen { rd() }; @@ -46,7 +46,7 @@ static void Fill_float_SSE(benchmark::State& state) { } } -static void Fill_float_SSE_unaligned(benchmark::State& state) { +static void FillSIMD_unaligned(benchmark::State& state) { Buffer buffer (state.range(0)); std::random_device rd { }; std::mt19937 gen { rd() }; @@ -56,20 +56,9 @@ static void Fill_float_SSE_unaligned(benchmark::State& state) { } } -static void Fill_double(benchmark::State& state) { - Buffer buffer (state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 1, 2 }; - for (auto _ : state) { - fill(absl::MakeSpan(buffer), dist(gen)); - } -} - BENCHMARK(Dummy)->Range((2<<6), (2<<16)); -BENCHMARK(Fill_float)->Range((2<<6), (2<<16)); -BENCHMARK(Fill_float_SSE)->Range((2<<6), (2<<16)); -BENCHMARK(Fill_float_unaligned)->Range((2<<6), (2<<16)); -BENCHMARK(Fill_float_SSE_unaligned)->Range((2<<6), (2<<16)); -BENCHMARK(Fill_double)->Range((2<<6), (2<<16)); +BENCHMARK(FillScalar)->Range((2<<6), (2<<16)); +BENCHMARK(FillSIMD)->Range((2<<6), (2<<16)); +BENCHMARK(FillScalar_unaligned)->Range((2<<6), (2<<16)); +BENCHMARK(FillSIMD_unaligned)->Range((2<<6), (2<<16)); BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/BM_ramp.cpp b/benchmarks/BM_ramp.cpp new file mode 100644 index 00000000..a8ccd4ef --- /dev/null +++ b/benchmarks/BM_ramp.cpp @@ -0,0 +1,123 @@ +#include +#include +#include "../sources/SIMDHelpers.h" +#include "../sources/Buffer.h" + + +static void Dummy(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + benchmark::DoNotOptimize(value); + } +} + +static void LinearScalar(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + linearRamp(absl::MakeSpan(output), 0.0f, value); + } +} + +static void LinearSIMD(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + linearRamp(absl::MakeSpan(output), 0.0f, value); + } +} +static void LinearScalarUnaligned(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + linearRamp(absl::MakeSpan(output).subspan(1), 0.0f, value); + } +} + +static void LinearSIMDUnaligned(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + linearRamp(absl::MakeSpan(output).subspan(1), 0.0f, value); + } +} + +static void MulScalar(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + multiplicativeRamp(absl::MakeSpan(output), 1.0f, value); + } +} + +static void MulSIMD(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + multiplicativeRamp(absl::MakeSpan(output), 1.0f, value); + } +} +static void MulScalarUnaligned(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + multiplicativeRamp(absl::MakeSpan(output).subspan(1), 1.0f, value); + } +} + +static void MulSIMDUnaligned(benchmark::State& state) { + Buffer output(state.range(0)); + std::random_device rd { }; + std::mt19937 gen { rd() }; + std::uniform_real_distribution dist { 1, 2 }; + for (auto _ : state) + { + auto value = dist(gen); + multiplicativeRamp(absl::MakeSpan(output).subspan(1), 1.0f, value); + } +} + +// Register the function as a benchmark +BENCHMARK(Dummy)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(LinearScalar)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(LinearSIMD)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(LinearScalarUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(LinearSIMDUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(MulScalar)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(MulSIMD)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(MulScalarUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK(MulSIMDUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12)); +BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/Cum_Prod.cpp b/benchmarks/Cum_Prod.cpp deleted file mode 100644 index 17c30438..00000000 --- a/benchmarks/Cum_Prod.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include "../sources/Intrinsics.h" -#include "../sources/Buffer.h" - - -static void Dummy(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 1, 2 }; - for (auto _ : state) - { - auto value = dist(gen); - benchmark::DoNotOptimize(value); - } -} - -static void Straight(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 1, 2 }; - for (auto _ : state) - { - auto value = dist(gen); - for (auto& out: output) - { - out = value; - value *= value; - } - } -} - -static void SIMD(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 1, 2 }; - for (auto _ : state) - { - auto value = dist(gen); - auto out = output.begin(); - const auto alignedEnd = state.range(0) - (state.range(0) & 3); - - auto baseReg = _mm_set_ps1(value); - auto prodReg = _mm_set_ps(value*value*value*value, value*value*value, value*value, value); - - while (out < output.data() + alignedEnd) - { - baseReg = _mm_mul_ps(baseReg, prodReg); - _mm_storeu_ps(out, baseReg); - baseReg = _mm_shuffle_ps(baseReg, baseReg, _MM_SHUFFLE(3, 3, 3, 3)); - out += 4; - } - - while (out < output.end()) - { - *out++ = value; - value *= value; - } - } -} - -static void SIMD_unaligned(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 1, 2 }; - for (auto _ : state) - { - auto value = dist(gen); - auto out = output.begin() + 1; - const auto alignedEnd = state.range(0) - (state.range(0) & 3); - - auto baseReg = _mm_set_ps1(value); - auto prodReg = _mm_set_ps(value*value*value*value, value*value*value, value*value, value); - - while (out < output.data() + alignedEnd) - { - baseReg = _mm_mul_ps(baseReg, prodReg); - _mm_storeu_ps(out, baseReg); - baseReg = _mm_shuffle_ps(baseReg, baseReg, _MM_SHUFFLE(3, 3, 3, 3)); - out += 4; - } - - while (out < output.end()) - { - *out++ = value; - value *= value; - } - } -} - -// Register the function as a benchmark -BENCHMARK(Dummy)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(Straight)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(SIMD)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(SIMD_unaligned)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK_MAIN(); \ No newline at end of file diff --git a/benchmarks/Cum_Sum.cpp b/benchmarks/Cum_Sum.cpp deleted file mode 100644 index d4d8746f..00000000 --- a/benchmarks/Cum_Sum.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include "../sources/Intrinsics.h" -#include "../sources/Buffer.h" - - -static void Dummy(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, 1 }; - for (auto _ : state) - { - auto value = dist(gen); - benchmark::DoNotOptimize(value); - } -} - -static void Straight(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, 1 }; - for (auto _ : state) - { - auto value = dist(gen); - for (auto& out: output) - { - out = value; - value *= value; - } - } -} - -static void SIMD(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, 1 }; - for (auto _ : state) - { - auto value = dist(gen); - auto out = output.begin(); - const auto alignedEnd = state.range(0) - (state.range(0) & 3); - - auto baseReg = _mm_set_ps1(value); - auto prodReg = _mm_set_ps(value+value+value+value, value+value+value, value+value, value); - - while (out < output.data() + alignedEnd) - { - baseReg = _mm_add_ps(baseReg, prodReg); - _mm_storeu_ps(out, baseReg); - baseReg = _mm_shuffle_ps(baseReg, baseReg, _MM_SHUFFLE(3, 3, 3, 3)); - out += 4; - } - - while (out < output.end()) - { - *out++ = value; - value *= value; - } - } -} - -static void SIMD_unaligned(benchmark::State& state) { - Buffer output(state.range(0)); - std::random_device rd { }; - std::mt19937 gen { rd() }; - std::uniform_real_distribution dist { 0, 1 }; - for (auto _ : state) - { - auto value = dist(gen); - auto out = output.begin() + 1; - const auto alignedEnd = state.range(0) - (state.range(0) & 3); - - auto baseReg = _mm_set_ps1(value); - auto prodReg = _mm_set_ps(value+value+value+value, value+value+value, value+value, value); - - while (out < output.data() + alignedEnd) - { - baseReg = _mm_add_ps(baseReg, prodReg); - _mm_storeu_ps(out, baseReg); - baseReg = _mm_shuffle_ps(baseReg, baseReg, _MM_SHUFFLE(3, 3, 3, 3)); - out += 4; - } - - while (out < output.end()) - { - *out++ = value; - value *= value; - } - } -} - -// Register the function as a benchmark -BENCHMARK(Dummy)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(Straight)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(SIMD)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK(SIMD_unaligned)->RangeMultiplier(2)->Range((1 << 2), (1 << 8)); -BENCHMARK_MAIN(); \ No newline at end of file diff --git a/sources/Globals.h b/sources/Globals.h index 50dde3b7..701c1463 100644 --- a/sources/Globals.h +++ b/sources/Globals.h @@ -25,9 +25,12 @@ namespace SIMDConfig constexpr unsigned int defaultAlignment { 16 }; constexpr bool writeInterleaved { true }; constexpr bool readInterleaved { true }; - constexpr bool fill { false }; + constexpr bool fill { true }; constexpr bool gain { false }; constexpr bool mathfuns { false }; + constexpr bool loopingSFZIndex { true }; + constexpr bool linearRamp { false }; + constexpr bool multiplicativeRamp { true }; #if USE_SIMD constexpr bool useSIMD { true }; #else diff --git a/sources/SIMDDummy.cpp b/sources/SIMDDummy.cpp index 14f52424..829c35e5 100644 --- a/sources/SIMDDummy.cpp +++ b/sources/SIMDDummy.cpp @@ -64,5 +64,17 @@ void applyGain(absl::Span gain, absl::Span void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeff, absl::Span rightCoeff, absl::Span indices, float floatIndex, float loopEnd, float loopStart) noexcept { - loopingSFZIndex( jumps, leftCoeff, rightCoeff, indices); + loopingSFZIndex(jumps, leftCoeff, rightCoeff, indices, floatIndex, loopEnd, loopStart); +} + +template<> +void linearRamp(absl::Span output, float start, float step) noexcept +{ + linearRamp(output, start, step); +} + +template<> +void multiplicativeRamp(absl::Span output, float start, float step) noexcept +{ + multiplicativeRamp(output, start, step); } \ No newline at end of file diff --git a/sources/SIMDHelpers.h b/sources/SIMDHelpers.h index 6e9261da..548806a6 100644 --- a/sources/SIMDHelpers.h +++ b/sources/SIMDHelpers.h @@ -144,12 +144,6 @@ void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeffs, absl:: template<> void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeff, absl::Span rightCoeff, absl::Span indices, float floatIndex, float loopEnd, float loopStart) noexcept; -template -void linearRamp(absl::Span output, T start, T end); - -template -void exponentialRamp(absl::Span output, T start, T end); - template inline void snippetGain(T gain, const T*& input, T*& output) { @@ -202,4 +196,41 @@ template<> void applyGain(float gain, absl::Span input, absl::Span output) noexcept; template<> -void applyGain(absl::Span gain, absl::Span input, absl::Span output) noexcept; \ No newline at end of file +void applyGain(absl::Span gain, absl::Span input, absl::Span output) noexcept; + +template +inline void snippetRampLinear(T*& output, T& value, T step) +{ + value += step; + *output++ = value; +} + +template +void linearRamp(absl::Span output, T start, T step) noexcept +{ + auto* out = output.begin(); + while(out < output.end()) + snippetRampLinear(out, start, step); +} + +template +inline void snippetRampMultiplicative(T*& output, T& value, T step) +{ + value *= step; + *output++ = value; +} + +template +void multiplicativeRamp(absl::Span output, T start, T step) noexcept +{ + auto* out = output.begin(); + while(out < output.end()) + snippetRampMultiplicative(out, start, step); +} + + +template<> +void linearRamp(absl::Span output, float start, float step) noexcept; + +template<> +void multiplicativeRamp(absl::Span output, float start, float step) noexcept; \ No newline at end of file diff --git a/sources/SIMDSSE.cpp b/sources/SIMDSSE.cpp index 1c616742..bce03f72 100644 --- a/sources/SIMDSSE.cpp +++ b/sources/SIMDSSE.cpp @@ -303,4 +303,54 @@ void loopingSFZIndex(absl::Span jumps, absl::Span(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); +} + +template<> +void linearRamp(absl::Span output, float value, float step) noexcept +{ + auto* out = output.begin(); + const auto* lastAligned = prevAligned(output.end()); + + while(unaligned(out) && out < lastAligned) + snippetRampLinear(out, value, step); + + auto mmValue = _mm_set1_ps(value); + auto mmStep = _mm_set_ps(step+step+step+step, step+step+step, step+step, step); + + while (out < lastAligned) + { + mmValue = _mm_add_ps(mmValue, mmStep); + _mm_store_ps(out, mmValue); + mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3)); + out += TypeAlignment; + } + + value = _mm_cvtss_f32(mmValue); + while(out < output.end()) + snippetRampLinear(out, value, step); +} + +template<> +void multiplicativeRamp(absl::Span output, float value, float step) noexcept +{ + auto* out = output.begin(); + const auto* lastAligned = prevAligned(output.end()); + + while(unaligned(out) && out < lastAligned) + snippetRampMultiplicative(out, value, step); + + auto mmValue = _mm_set1_ps(value); + auto mmStep = _mm_set_ps(step*step*step*step, step*step*step, step*step, step); + + while (out < lastAligned) + { + mmValue = _mm_mul_ps(mmValue, mmStep); + _mm_store_ps(out, mmValue); + mmValue = _mm_shuffle_ps(mmValue, mmValue, _MM_SHUFFLE(3, 3, 3, 3)); + out += TypeAlignment; + } + + value = _mm_cvtss_f32(mmValue); + while(out < output.end()) + snippetRampMultiplicative(out, value, step); } \ No newline at end of file diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index d0d58171..f2801736 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -406,4 +406,84 @@ TEST_CASE("[Helpers] SFZ looping index (SIMD)") // REQUIRE( approxEqual(indices, indicesSIMD, 1) ); // REQUIRE( approxEqual(leftCoeffs, leftCoeffsSIMD, 1e-2) ); // REQUIRE( approxEqual(rightCoeffs, rightCoeffsSIMD, 1e-2) ); -// } \ No newline at end of file +// } + +TEST_CASE("[Helpers] Linear Ramp") +{ + const float start { 0.0f }; + const float v { fillValue }; + std::array output; + std::array expected {v, v + v, v + v + v, v + v + v + v, v + v + v + v + v, v + v + v + v + v + v} ; + linearRamp(absl::MakeSpan(output), start, v); + REQUIRE( output == expected ); +} + +TEST_CASE("[Helpers] Linear Ramp (SIMD)") +{ + const float start { 0.0f }; + const float v { fillValue }; + std::array output; + std::array expected {v, v + v, v + v + v, v + v + v + v, v + v + v + v + v, v + v + v + v + v + v} ; + linearRamp(absl::MakeSpan(output), start, v); + REQUIRE( output == expected ); +} + +TEST_CASE("[Helpers] Linear Ramp (SIMD vs scalar)") +{ + const float start { 0.0f }; + std::vector outputScalar(bigBufferSize); + std::vector outputSIMD(bigBufferSize); + linearRamp(absl::MakeSpan(outputScalar), start, fillValue); + linearRamp(absl::MakeSpan(outputSIMD), start, fillValue); + REQUIRE( approxEqual(outputScalar, outputSIMD) ); +} + +TEST_CASE("[Helpers] Linear Ramp unaligned (SIMD vs scalar)") +{ + const float start { 0.0f }; + std::vector outputScalar(bigBufferSize); + std::vector outputSIMD(bigBufferSize); + linearRamp(absl::MakeSpan(outputScalar).subspan(1), start, fillValue); + linearRamp(absl::MakeSpan(outputSIMD).subspan(1), start, fillValue); + REQUIRE( approxEqual(outputScalar, outputSIMD) ); +} + +TEST_CASE("[Helpers] Multiplicative Ramp") +{ + const float start { 1.0f }; + const float v { fillValue }; + std::array output; + std::array expected {v, v * v, v * v * v, v * v * v * v, v * v * v * v * v, v * v * v * v * v * v} ; + multiplicativeRamp(absl::MakeSpan(output), start, v); + REQUIRE( output == expected ); +} + +TEST_CASE("[Helpers] Multiplicative Ramp (SIMD)") +{ + const float start { 1.0f }; + const float v { fillValue }; + std::array output; + std::array expected {v, v * v, v * v * v, v * v * v * v, v * v * v * v * v, v * v * v * v * v * v} ; + multiplicativeRamp(absl::MakeSpan(output), start, v); + REQUIRE( output == expected ); +} + +TEST_CASE("[Helpers] Multiplicative Ramp (SIMD vs scalar)") +{ + const float start { 1.0f }; + std::vector outputScalar(bigBufferSize); + std::vector outputSIMD(bigBufferSize); + multiplicativeRamp(absl::MakeSpan(outputScalar), start, fillValue); + multiplicativeRamp(absl::MakeSpan(outputSIMD), start, fillValue); + REQUIRE( approxEqual(outputScalar, outputSIMD) ); +} + +TEST_CASE("[Helpers] Multiplicative Ramp unaligned (SIMD vs scalar)") +{ + const float start { 1.0f }; + std::vector outputScalar(bigBufferSize); + std::vector outputSIMD(bigBufferSize); + multiplicativeRamp(absl::MakeSpan(outputScalar).subspan(1), start, fillValue); + multiplicativeRamp(absl::MakeSpan(outputSIMD).subspan(1), start, fillValue); + REQUIRE( approxEqual(outputScalar, outputSIMD) ); +} \ No newline at end of file