Moved divide to the new format

This commit is contained in:
Paul Ferrand 2020-05-30 22:26:35 +02:00 committed by Jean Pierre Cimalando
parent 1ab1ab802b
commit 1b68331f38
4 changed files with 49 additions and 54 deletions

View file

@ -46,28 +46,28 @@ BENCHMARK_DEFINE_F(Divide, Straight)(benchmark::State& state) {
BENCHMARK_DEFINE_F(Divide, Scalar)(benchmark::State& state) { BENCHMARK_DEFINE_F(Divide, Scalar)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::divide<float, false>(input, divisor, absl::MakeSpan(output)); sfz::divide<float>(input, divisor, absl::MakeSpan(output));
} }
} }
BENCHMARK_DEFINE_F(Divide, SIMD)(benchmark::State& state) { BENCHMARK_DEFINE_F(Divide, SIMD)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::divide<float, true>(input, divisor, absl::MakeSpan(output)); sfz::divide<float>(input, divisor, absl::MakeSpan(output));
} }
} }
BENCHMARK_DEFINE_F(Divide, Scalar_Unaligned)(benchmark::State& state) { BENCHMARK_DEFINE_F(Divide, Scalar_Unaligned)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::divide<float, false>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); sfz::divide<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1));
} }
} }
BENCHMARK_DEFINE_F(Divide, SIMD_Unaligned)(benchmark::State& state) { BENCHMARK_DEFINE_F(Divide, SIMD_Unaligned)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::divide<float, true>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); sfz::divide<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1));
} }
} }

View file

@ -188,4 +188,30 @@ void applyGain<float>(const float* gain, const float* input, float* output, unsi
*output++ = (*gain++) * (*input++); *output++ = (*gain++) * (*input++);
} }
template <>
void sfz::divide<float>(const float* input, const float* divisor, float* output, unsigned size) noexcept
{
const auto sentinel = output + size;
if (getSIMDOpStatus(SIMDOps::divide)) {
#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386
if (cpuInfo.has_sse()) {
const auto* lastAligned = prevAligned(sentinel);
while (unaligned(input, output) && output < lastAligned)
*output++ = (*input++) / (*divisor++);
while (output < lastAligned) {
_mm_store_ps(output, _mm_div_ps(_mm_load_ps(input), _mm_load_ps(divisor)));
incrementAll<4>(divisor, input, output);
}
// fallthrough from lastAligned to sentinel
}
#endif
}
while (output < sentinel)
*output++ = (*input++) / (*divisor++);
}
} }

View file

@ -242,56 +242,49 @@ inline void applyGain(absl::Span<const T> gain, absl::Span<T> array) noexcept
applyGain<T>(gain.data(), array.data(), array.data(), minSpanSize(gain, array)); applyGain<T>(gain.data(), array.data(), array.data(), minSpanSize(gain, array));
} }
namespace _internals {
template <class T>
inline void snippetDivSpan(const T*& input, const T*& divisor,T*& output)
{
*output++ = (*input++) / (*divisor++);
}
}
/** /**
* @brief Divide a vector by another vector * @brief Divide a vector by another vector
* *
* The output size will be the minimum of the divisor, input span and output span size. * The output size will be the minimum of the divisor, input span and output span size.
* *
* @tparam T the underlying type * @tparam T the underlying type
* @tparam SIMD use the SIMD version or the scalar version
* @param input * @param input
* @param divisor * @param divisor
* @param output * @param output
* @param size
*/ */
template <class T, bool SIMD = SIMDConfig::divide> template <class T>
void divide(absl::Span<const T> input, absl::Span<const T> divisor, absl::Span<T> output) noexcept void divide(const T* input, const T* divisor, T* output, unsigned size) noexcept
{ {
CHECK(divisor.size() == input.size()); const auto sentinel = output + size;
CHECK(input.size() <= output.size()); while (output < sentinel)
auto* in = input.begin(); *output++ = (*input++) / (*divisor++);
auto* d = divisor.begin(); }
auto* out = output.begin();
auto* sentinel = out + std::min(divisor.size(), std::min(output.size(), input.size())); template <>
while (out < sentinel) void divide<float>(const float* input, const float* divisor, float* output, unsigned size) noexcept;
_internals::snippetDivSpan<T>(in, d, out);
template <class T>
inline void divide(absl::Span<const T> input, absl::Span<const T> divisor, absl::Span<T> output) noexcept
{
CHECK_SPAN_SIZES(input, divisor, output);
divide<T>(input.data(), divisor.data(), output.data(), minSpanSize(input, divisor, output));
} }
/** /**
* @brief Divide a vector by another in place * @brief Divide a vector by another in place
* *
* @tparam T the underlying type * @tparam T the underlying type
* @tparam SIMD use the SIMD version or the scalar version
* @param output * @param output
* @param divisor * @param divisor
*/ */
template <class T, bool SIMD = SIMDConfig::divide> template <class T>
void divide(absl::Span<T> output, absl::Span<const T> divisor) noexcept void divide(absl::Span<T> output, absl::Span<const T> divisor) noexcept
{ {
divide<T, SIMD>(output, divisor, output); CHECK_SPAN_SIZES(divisor, output);
divide<T>(output.data(), divisor.data(), output.data(), minSpanSize(divisor, output));
} }
template <>
void divide<float, true>(absl::Span<const float> input, absl::Span<const float> divisor, absl::Span<float> output) noexcept;
namespace _internals { namespace _internals {
template <class T> template <class T>
inline void snippetMultiplyAdd(const T*& gain, const T*& input, T*& output) inline void snippetMultiplyAdd(const T*& gain, const T*& input, T*& output)

View file

@ -16,30 +16,6 @@
constexpr uintptr_t TypeAlignment = 4; constexpr uintptr_t TypeAlignment = 4;
template <>
void sfz::divide<float, true>(absl::Span<const float> input, absl::Span<const float> divisor, absl::Span<float> output) noexcept
{
auto* in = input.begin();
auto* out = output.begin();
auto* div = divisor.begin();
const auto size = std::min(output.size(), std::min(input.size(), divisor.size()));
const auto* lastAligned = prevAligned(output.begin() + size);
while (unaligned(out, in, div) && out < lastAligned)
_internals::snippetDivSpan<float>(in, div, out);
while (out < lastAligned) {
_mm_store_ps(out, _mm_div_ps(_mm_load_ps(in), _mm_load_ps(div)));
incrementAll<TypeAlignment>(in, div, out);
}
while (out < output.end())
_internals::snippetDivSpan<float>(in, div, out);
}
template <> template <>
void sfz::multiplyAdd<float, true>(absl::Span<const float> gain, absl::Span<const float> input, absl::Span<float> output) noexcept void sfz::multiplyAdd<float, true>(absl::Span<const float> gain, absl::Span<const float> input, absl::Span<float> output) noexcept
{ {