Move subtract to the new format
This commit is contained in:
parent
3cb8164068
commit
af855d3993
5 changed files with 112 additions and 97 deletions
|
|
@ -36,28 +36,32 @@ public:
|
||||||
BENCHMARK_DEFINE_F(SubArray, Scalar)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(SubArray, Scalar)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::subtract<float, false>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false);
|
||||||
|
sfz::subtract<float>(input, absl::MakeSpan(output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(SubArray, SIMD)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(SubArray, SIMD)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::subtract<float, true>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true);
|
||||||
|
sfz::subtract<float>(input, absl::MakeSpan(output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(SubArray, Scalar_Unaligned)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(SubArray, Scalar_Unaligned)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::subtract<float, false>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false);
|
||||||
|
sfz::subtract<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(SubArray, SIMD_Unaligned)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(SubArray, SIMD_Unaligned)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::subtract<float, true>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true);
|
||||||
|
sfz::subtract<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -392,4 +392,57 @@ void add<float>(float value, float* output, unsigned size) noexcept
|
||||||
*output++ += value;
|
*output++ += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void subtract<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
|
{
|
||||||
|
const auto sentinel = output + size;
|
||||||
|
|
||||||
|
if (getSIMDOpStatus(SIMDOps::subtract)) {
|
||||||
|
#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++;
|
||||||
|
|
||||||
|
while (output < lastAligned) {
|
||||||
|
_mm_store_ps(output, _mm_sub_ps(_mm_load_ps(output), _mm_load_ps(input)));
|
||||||
|
incrementAll<4>(input, output);
|
||||||
|
}
|
||||||
|
// fallthrough from lastAligned to sentinel
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (output < sentinel)
|
||||||
|
*output++ -= *input++;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void subtract<float>(float value, float* output, unsigned size) noexcept
|
||||||
|
{
|
||||||
|
const auto sentinel = output + size;
|
||||||
|
|
||||||
|
if (getSIMDOpStatus(SIMDOps::subtract)) {
|
||||||
|
#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386
|
||||||
|
if (cpuInfo.has_sse()) {
|
||||||
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
|
|
||||||
|
while (unaligned(output) && output < lastAligned)
|
||||||
|
*output++ -= value;
|
||||||
|
|
||||||
|
const auto mmValue = _mm_set1_ps(value);
|
||||||
|
while (output < lastAligned) {
|
||||||
|
_mm_store_ps(output, _mm_sub_ps(_mm_load_ps(output), mmValue));
|
||||||
|
incrementAll<4>(output);
|
||||||
|
}
|
||||||
|
// fallthrough from lastAligned to sentinel
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (output < sentinel)
|
||||||
|
*output++ -= value;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -450,63 +450,56 @@ void add(T value, absl::Span<T> output) noexcept
|
||||||
add<T>(value, output.data(), output.size());
|
add<T>(value, output.data(), output.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace _internals {
|
|
||||||
template <class T>
|
|
||||||
inline void snippetSubtract(const T*& input, T*& output)
|
|
||||||
{
|
|
||||||
*output++ -= *input++;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void snippetSubtract(const T value, T*& output)
|
|
||||||
{
|
|
||||||
*output++ -= value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subtract a value from a span
|
* @brief Subtract an input span from the output span
|
||||||
*
|
*
|
||||||
* @tparam T the underlying type
|
* @tparam T the underlying type
|
||||||
* @tparam SIMD use the SIMD version or the scalar version
|
|
||||||
* @param value
|
|
||||||
* @param output
|
|
||||||
*/
|
|
||||||
template <class T, bool SIMD = SIMDConfig::subtract>
|
|
||||||
void subtract(const T value, absl::Span<T> output) noexcept
|
|
||||||
{
|
|
||||||
auto* out = output.begin();
|
|
||||||
auto* sentinel = output.end();
|
|
||||||
while (out < sentinel)
|
|
||||||
_internals::snippetSubtract(value, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Subtract a span from another span
|
|
||||||
*
|
|
||||||
* The output size will be the minimum of the input span and output span sizes.
|
|
||||||
*
|
|
||||||
* @tparam T the underlying type
|
|
||||||
* @tparam SIMD use the SIMD version or the scalar version
|
|
||||||
* @param input
|
* @param input
|
||||||
* @param output
|
* @param output
|
||||||
|
* @param size
|
||||||
*/
|
*/
|
||||||
template <class T, bool SIMD = SIMDConfig::subtract>
|
template <class T>
|
||||||
void subtract(absl::Span<const T> input, absl::Span<T> output) noexcept
|
void subtract(const T* input, T* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
CHECK(output.size() >= input.size());
|
const auto sentinel = output + size;
|
||||||
auto* in = input.begin();
|
while (output < sentinel)
|
||||||
auto* out = output.begin();
|
*output++ -= *input++;
|
||||||
auto* sentinel = out + min(input.size(), output.size());
|
|
||||||
while (out < sentinel)
|
|
||||||
_internals::snippetSubtract(in, out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void subtract<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept;
|
void subtract<float>(const float* input, float* output, unsigned size) noexcept;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void subtract(absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||||
|
{
|
||||||
|
CHECK_SPAN_SIZES(input, output);
|
||||||
|
subtract<T>(input.data(), output.data(), minSpanSize(input, output));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Subtract a value inplace
|
||||||
|
*
|
||||||
|
* @tparam T the underlying type
|
||||||
|
* @param value
|
||||||
|
* @param output
|
||||||
|
* @param size
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
void subtract(T value, T* output, unsigned size) noexcept
|
||||||
|
{
|
||||||
|
const auto sentinel = output + size;
|
||||||
|
while (output < sentinel)
|
||||||
|
*output++ -= value;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void subtract<float, true>(const float value, absl::Span<float> output) noexcept;
|
void subtract<float>(float value, float* output, unsigned size) noexcept;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void subtract(T value, absl::Span<T> output) noexcept
|
||||||
|
{
|
||||||
|
subtract<T>(value, output.data(), output.size());
|
||||||
|
}
|
||||||
|
|
||||||
namespace _internals {
|
namespace _internals {
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
|
||||||
|
|
@ -16,47 +16,6 @@
|
||||||
|
|
||||||
constexpr uintptr_t TypeAlignment = 4;
|
constexpr uintptr_t TypeAlignment = 4;
|
||||||
|
|
||||||
template <>
|
|
||||||
void sfz::subtract<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
|
||||||
{
|
|
||||||
CHECK(output.size() >= input.size());
|
|
||||||
auto* in = input.begin();
|
|
||||||
auto* out = output.begin();
|
|
||||||
auto* sentinel = out + min(input.size(), output.size());
|
|
||||||
const auto* lastAligned = prevAligned(sentinel);
|
|
||||||
|
|
||||||
while (unaligned(in, out) && out < lastAligned)
|
|
||||||
_internals::snippetSubtract<float>(in, out);
|
|
||||||
|
|
||||||
while (out < lastAligned) {
|
|
||||||
_mm_store_ps(out, _mm_sub_ps(_mm_load_ps(out), _mm_load_ps(in)));
|
|
||||||
incrementAll<TypeAlignment>(in, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (out < sentinel)
|
|
||||||
_internals::snippetSubtract<float>(in, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
void sfz::subtract<float, true>(const 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)
|
|
||||||
_internals::snippetSubtract<float>(value, out);
|
|
||||||
|
|
||||||
auto mmValue = _mm_set_ps1(value);
|
|
||||||
while (out < lastAligned) {
|
|
||||||
_mm_store_ps(out, _mm_sub_ps(_mm_load_ps(out), mmValue));
|
|
||||||
out += TypeAlignment;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (out < sentinel)
|
|
||||||
_internals::snippetSubtract<float>(value, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void sfz::copy<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
void sfz::copy<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,7 @@ TEST_CASE("[Helpers] Subtract")
|
||||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||||
std::array<float, 5> output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
std::array<float, 5> output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
std::array<float, 5> expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f };
|
std::array<float, 5> expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f };
|
||||||
sfz::subtract<float, false>(input, absl::MakeSpan(output));
|
sfz::subtract<float>(input, absl::MakeSpan(output));
|
||||||
REQUIRE(output == expected);
|
REQUIRE(output == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -570,7 +570,8 @@ TEST_CASE("[Helpers] Subtract 2")
|
||||||
{
|
{
|
||||||
std::array<float, 5> output { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
std::array<float, 5> output { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||||
std::array<float, 5> expected { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f };
|
std::array<float, 5> expected { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f };
|
||||||
sfz::subtract<float, false>(1.0f, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false);
|
||||||
|
sfz::subtract<float>(1.0f, absl::MakeSpan(output));
|
||||||
REQUIRE(output == expected);
|
REQUIRE(output == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -580,7 +581,8 @@ TEST_CASE("[Helpers] Subtract (SIMD)")
|
||||||
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
std::array<float, 5> input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
|
||||||
std::array<float, 5> output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
std::array<float, 5> output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
std::array<float, 5> expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f };
|
std::array<float, 5> expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f };
|
||||||
sfz::subtract<float, true>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true);
|
||||||
|
sfz::subtract<float>(input, absl::MakeSpan(output));
|
||||||
REQUIRE(output == expected);
|
REQUIRE(output == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -593,8 +595,10 @@ TEST_CASE("[Helpers] Subtract (SIMD vs scalar)")
|
||||||
absl::c_fill(outputScalar, 0.0f);
|
absl::c_fill(outputScalar, 0.0f);
|
||||||
absl::c_fill(outputSIMD, 0.0f);
|
absl::c_fill(outputSIMD, 0.0f);
|
||||||
|
|
||||||
sfz::subtract<float, false>(input, absl::MakeSpan(outputScalar));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false);
|
||||||
sfz::subtract<float, true>(input, absl::MakeSpan(outputSIMD));
|
sfz::subtract<float>(input, absl::MakeSpan(outputScalar));
|
||||||
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true);
|
||||||
|
sfz::subtract<float>(input, absl::MakeSpan(outputSIMD));
|
||||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -605,8 +609,10 @@ TEST_CASE("[Helpers] Subtract 2 (SIMD vs scalar)")
|
||||||
absl::c_iota(outputScalar, 0.0f);
|
absl::c_iota(outputScalar, 0.0f);
|
||||||
absl::c_iota(outputSIMD, 0.0f);
|
absl::c_iota(outputSIMD, 0.0f);
|
||||||
|
|
||||||
sfz::subtract<float, false>(1.2f, absl::MakeSpan(outputScalar));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false);
|
||||||
sfz::subtract<float, true>(1.2f, absl::MakeSpan(outputSIMD));
|
sfz::subtract<float>(1.2f, absl::MakeSpan(outputScalar));
|
||||||
|
sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true);
|
||||||
|
sfz::subtract<float>(1.2f, absl::MakeSpan(outputSIMD));
|
||||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue