Move diff to the new format
This commit is contained in:
parent
a83cd99040
commit
ba87df8009
5 changed files with 80 additions and 81 deletions
|
|
@ -37,28 +37,32 @@ public:
|
||||||
BENCHMARK_DEFINE_F(DiffArray, Diff_Scalar)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(DiffArray, Diff_Scalar)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::diff<float, false>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, false);
|
||||||
|
sfz::diff<float>(input, absl::MakeSpan(output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(DiffArray, Diff_SIMD)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(DiffArray, Diff_SIMD)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::diff<float, true>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, true);
|
||||||
|
sfz::diff<float>(input, absl::MakeSpan(output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(DiffArray, Diff_Scalar_Unaligned)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(DiffArray, Diff_Scalar_Unaligned)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::diff<float, false>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, false);
|
||||||
|
sfz::diff<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BENCHMARK_DEFINE_F(DiffArray, Diff_SIMD_Unaligned)(benchmark::State& state) {
|
BENCHMARK_DEFINE_F(DiffArray, Diff_SIMD_Unaligned)(benchmark::State& state) {
|
||||||
for (auto _ : state)
|
for (auto _ : state)
|
||||||
{
|
{
|
||||||
sfz::diff<float, true>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, true);
|
||||||
|
sfz::diff<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -569,8 +569,8 @@ void cumsum<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
const auto* lastAligned = prevAligned(sentinel);
|
const auto* lastAligned = prevAligned(sentinel);
|
||||||
|
|
||||||
while (unaligned(input, output) && output < lastAligned) {
|
while (unaligned(input, output) && output < lastAligned) {
|
||||||
*output = *(output - 1) + *input++;
|
*output = *(output - 1) + *input;
|
||||||
output++;
|
incrementAll(input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mmOutput = _mm_set_ps1(*(output - 1));
|
auto mmOutput = _mm_set_ps1(*(output - 1));
|
||||||
|
|
@ -589,8 +589,48 @@ void cumsum<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
while (output < sentinel) {
|
while (output < sentinel) {
|
||||||
*output = *(output - 1) + *input++;
|
*output = *(output - 1) + *input;
|
||||||
output++;
|
incrementAll(input, output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
void diff<float>(const float* input, float* output, unsigned size) noexcept
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto sentinel = output + size;
|
||||||
|
*output++ = *input++;
|
||||||
|
|
||||||
|
if (getSIMDOpStatus(SIMDOps::diff)) {
|
||||||
|
#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 - *(input - 1);
|
||||||
|
incrementAll(input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto mmBase = _mm_set_ps1(*(input - 1));
|
||||||
|
while (output < lastAligned) {
|
||||||
|
auto mmOutput = _mm_load_ps(input);
|
||||||
|
auto mmNextBase = _mm_shuffle_ps(mmOutput, mmOutput, _MM_SHUFFLE(3, 3, 3, 3));
|
||||||
|
mmOutput = _mm_sub_ps(mmOutput, mmBase);
|
||||||
|
mmBase = mmNextBase;
|
||||||
|
mmOutput = _mm_sub_ps(mmOutput, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOutput), 4)));
|
||||||
|
_mm_store_ps(output, mmOutput);
|
||||||
|
incrementAll<4>(input, output);
|
||||||
|
}
|
||||||
|
// fallthrough from lastAligned to sentinel
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (output < sentinel) {
|
||||||
|
*output = *input - *(input - 1);
|
||||||
|
incrementAll(input, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -590,21 +590,10 @@ T meanSquared(absl::Span<const T> vector) noexcept
|
||||||
return meanSquared(vector.data(), vector.size());
|
return meanSquared(vector.data(), vector.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace _internals {
|
|
||||||
template <class T>
|
|
||||||
inline void snippetCumsum(const T*& input, T*& output)
|
|
||||||
{
|
|
||||||
*output = *(output - 1) + *input++;
|
|
||||||
output++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Computes the cumulative sum of a span.
|
* @brief Computes the cumulative sum of a span.
|
||||||
* The first output is the same as the first input.
|
* The first output is the same as the first input.
|
||||||
*
|
*
|
||||||
* The output size will be the minimum of the input span and output span sizes.
|
|
||||||
*
|
|
||||||
* @tparam T the underlying type
|
* @tparam T the underlying type
|
||||||
* @param input
|
* @param input
|
||||||
* @param output
|
* @param output
|
||||||
|
|
@ -620,8 +609,8 @@ void cumsum(const T* input, T* output, unsigned size) noexcept
|
||||||
|
|
||||||
*output++ = *input++;
|
*output++ = *input++;
|
||||||
while (output < sentinel) {
|
while (output < sentinel) {
|
||||||
*output = *(output - 1) + *input++;
|
*output = *(output - 1) + *input;
|
||||||
output++;
|
incrementAll(input, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -672,44 +661,38 @@ void sfzInterpolationCast(absl::Span<const T> floatJumps, absl::Span<int> jumps,
|
||||||
_internals::snippetSFZInterpolationCast(floatJump, jump, coeff);
|
_internals::snippetSFZInterpolationCast(floatJump, jump, coeff);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace _internals {
|
|
||||||
template <class T>
|
|
||||||
inline void snippetDiff(const T*& input, T*& output)
|
|
||||||
{
|
|
||||||
*output = *input - *(input - 1);
|
|
||||||
output++;
|
|
||||||
input++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Computes the differential of a span (successive differences).
|
* @brief Computes the differential of a span (successive differences).
|
||||||
* The first output is the same as the first input.
|
* The first output is the same as the first input.
|
||||||
*
|
*
|
||||||
* The output size will be the minimum of the input span and output span sizes.
|
|
||||||
*
|
|
||||||
* @tparam T the underlying type
|
* @tparam T the underlying type
|
||||||
* @tparam SIMD use the SIMD version or the scalar version
|
* @param input
|
||||||
* @param vector
|
* @param output
|
||||||
* @return T
|
* @param size
|
||||||
*/
|
*/
|
||||||
template <class T, bool SIMD = SIMDConfig::diff>
|
template <class T>
|
||||||
void diff(absl::Span<const T> input, absl::Span<T> output) noexcept
|
void diff(const T* input, T* output, unsigned size) noexcept
|
||||||
{
|
{
|
||||||
CHECK(output.size() >= input.size());
|
if (size == 0)
|
||||||
if (input.size() == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto out = output.data();
|
const auto sentinel = output + size;
|
||||||
auto in = input.data();
|
|
||||||
const auto sentinel = in + std::min(input.size(), output.size());
|
|
||||||
|
|
||||||
*out++ = *in++;
|
*output++ = *input++;
|
||||||
while (in < sentinel)
|
while (output < sentinel) {
|
||||||
_internals::snippetDiff(in, out);
|
*output = *input - *(input - 1);
|
||||||
|
incrementAll(input, output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void diff<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept;
|
void diff<float>(const float* input, float* output, unsigned size) noexcept;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void diff(absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||||
|
{
|
||||||
|
CHECK_SPAN_SIZES(input, output);
|
||||||
|
diff<T>(input.data(), output.data(), minSpanSize(input, output));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace sfz
|
} // namespace sfz
|
||||||
|
|
|
||||||
|
|
@ -16,35 +16,4 @@
|
||||||
|
|
||||||
constexpr uintptr_t TypeAlignment = 4;
|
constexpr uintptr_t TypeAlignment = 4;
|
||||||
|
|
||||||
template <>
|
|
||||||
void sfz::diff<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
|
||||||
{
|
|
||||||
CHECK(output.size() >= input.size());
|
|
||||||
if (input.size() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto out = output.data();
|
|
||||||
auto in = input.data();
|
|
||||||
const auto sentinel = in + std::min(input.size(), output.size());
|
|
||||||
const auto lastAligned = prevAligned(sentinel);
|
|
||||||
|
|
||||||
*out++ = *in++;
|
|
||||||
while (unaligned(in, out) && in < lastAligned)
|
|
||||||
_internals::snippetDiff(in, out);
|
|
||||||
|
|
||||||
auto mmBase = _mm_set_ps1(*(in - 1));
|
|
||||||
while (in < lastAligned) {
|
|
||||||
auto mmOutput = _mm_load_ps(in);
|
|
||||||
auto mmNextBase = _mm_shuffle_ps(mmOutput, mmOutput, _MM_SHUFFLE(3, 3, 3, 3));
|
|
||||||
mmOutput = _mm_sub_ps(mmOutput, mmBase);
|
|
||||||
mmBase = mmNextBase;
|
|
||||||
mmOutput = _mm_sub_ps(mmOutput, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(mmOutput), 4)));
|
|
||||||
_mm_store_ps(out, mmOutput);
|
|
||||||
incrementAll<TypeAlignment>(in, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (in < sentinel)
|
|
||||||
_internals::snippetDiff(in, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SFIZZ_HAVE_SSE2
|
#endif // SFIZZ_HAVE_SSE2
|
||||||
|
|
|
||||||
|
|
@ -720,7 +720,8 @@ TEST_CASE("[Helpers] Diff")
|
||||||
std::array<float, 6> input { 1.1f, 2.3f, 3.6f, 5.0f, 6.5f, 8.1f };
|
std::array<float, 6> input { 1.1f, 2.3f, 3.6f, 5.0f, 6.5f, 8.1f };
|
||||||
std::array<float, 6> output;
|
std::array<float, 6> output;
|
||||||
std::array<float, 6> expected { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f };
|
std::array<float, 6> expected { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f };
|
||||||
sfz::diff<float, false>(input, absl::MakeSpan(output));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, false);
|
||||||
|
sfz::diff<float>(input, absl::MakeSpan(output));
|
||||||
REQUIRE(approxEqual<float>(output, expected));
|
REQUIRE(approxEqual<float>(output, expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -731,8 +732,10 @@ TEST_CASE("[Helpers] Diff (SIMD vs Scalar)")
|
||||||
std::vector<float> outputSIMD(bigBufferSize);
|
std::vector<float> outputSIMD(bigBufferSize);
|
||||||
sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, true);
|
sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, true);
|
||||||
sfz::linearRamp<float>(absl::MakeSpan(input), 0.0f, 0.1f);
|
sfz::linearRamp<float>(absl::MakeSpan(input), 0.0f, 0.1f);
|
||||||
sfz::diff<float, false>(input, absl::MakeSpan(outputScalar));
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, false);
|
||||||
sfz::diff<float, true>(input, absl::MakeSpan(outputSIMD));
|
sfz::diff<float>(input, absl::MakeSpan(outputScalar));
|
||||||
|
sfz::setSIMDOpStatus(sfz::SIMDOps::diff, true);
|
||||||
|
sfz::diff<float>(input, absl::MakeSpan(outputSIMD));
|
||||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue