Move cumsum to the new format
This commit is contained in:
parent
59f284a82b
commit
a83cd99040
7 changed files with 77 additions and 55 deletions
|
|
@ -35,28 +35,32 @@ public:
|
|||
BENCHMARK_DEFINE_F(CumArray, Sum_Scalar)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::cumsum<float, false>(input, absl::MakeSpan(output));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, false);
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(CumArray, Sum_SIMD)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::cumsum<float, true>(input, absl::MakeSpan(output));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, true);
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(output));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(CumArray, Sum_Scalar_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::cumsum<float, false>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, false);
|
||||
sfz::cumsum<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_DEFINE_F(CumArray, Sum_SIMD_Unaligned)(benchmark::State& state) {
|
||||
for (auto _ : state)
|
||||
{
|
||||
sfz::cumsum<float, true>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, true);
|
||||
sfz::cumsum<float>(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ public:
|
|||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
sfz::cumsum<float, false>(input, absl::MakeSpan(input));
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(input));
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */) {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public:
|
|||
input = std::vector<float>(state.range(0));
|
||||
output = std::vector<float>(state.range(0));
|
||||
std::generate(input.begin(), input.end(), [&]() { return dist(gen); });
|
||||
sfz::cumsum<float, false>(input, absl::MakeSpan(input));
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(input));
|
||||
}
|
||||
|
||||
void TearDown(const ::benchmark::State& /* state */)
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ float meanSquared<float>(const float* vector, unsigned size) noexcept
|
|||
#endif
|
||||
}
|
||||
|
||||
while (vector < sentinel){
|
||||
while (vector < sentinel) {
|
||||
result += (*vector) * (*vector);
|
||||
vector++;
|
||||
}
|
||||
|
|
@ -554,4 +554,44 @@ float meanSquared<float>(const float* vector, unsigned size) noexcept
|
|||
return result / static_cast<float>(size);
|
||||
}
|
||||
|
||||
template <>
|
||||
void cumsum<float>(const float* input, float* output, unsigned size) noexcept
|
||||
{
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
const auto sentinel = output + size;
|
||||
*output++ = *input++;
|
||||
|
||||
if (getSIMDOpStatus(SIMDOps::cumsum)) {
|
||||
#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 = *(output - 1) + *input++;
|
||||
output++;
|
||||
}
|
||||
|
||||
auto mmOutput = _mm_set_ps1(*(output - 1));
|
||||
while (output < lastAligned) {
|
||||
auto mmOffset = _mm_load_ps(input);
|
||||
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, _MM_SHUFFLE(1, 0, 0, 0)));
|
||||
mmOutput = _mm_add_ps(mmOutput, mmOffset);
|
||||
_mm_store_ps(output, mmOutput);
|
||||
mmOutput = _mm_shuffle_ps(mmOutput, mmOutput, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
incrementAll<4>(input, output);
|
||||
}
|
||||
// fallthrough from lastAligned to sentinel
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
while (output < sentinel) {
|
||||
*output = *(output - 1) + *input++;
|
||||
output++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -606,28 +606,34 @@ namespace _internals {
|
|||
* 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 vector
|
||||
* @return T
|
||||
* @param input
|
||||
* @param output
|
||||
* @param size
|
||||
*/
|
||||
template <class T, bool SIMD = SIMDConfig::cumsum>
|
||||
void cumsum(absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||
template <class T>
|
||||
void cumsum(const T* input, T* output, unsigned size) noexcept
|
||||
{
|
||||
CHECK(output.size() >= input.size());
|
||||
if (input.size() == 0)
|
||||
if (size == 0)
|
||||
return;
|
||||
|
||||
auto out = output.data();
|
||||
auto in = input.data();
|
||||
const auto sentinel = in + std::min(input.size(), output.size());
|
||||
const auto sentinel = output + size;
|
||||
|
||||
*out++ = *in++;
|
||||
while (in < sentinel)
|
||||
_internals::snippetCumsum(in, out);
|
||||
*output++ = *input++;
|
||||
while (output < sentinel) {
|
||||
*output = *(output - 1) + *input++;
|
||||
output++;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void cumsum<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept;
|
||||
void cumsum<float>(const float* input, float* output, unsigned size) noexcept;
|
||||
|
||||
template <class T>
|
||||
void cumsum(absl::Span<const T> input, absl::Span<T> output) noexcept
|
||||
{
|
||||
CHECK_SPAN_SIZES(input, output);
|
||||
cumsum<T>(input.data(), output.data(), minSpanSize(input, output));
|
||||
}
|
||||
|
||||
// FIXME: This should go away once the changes from the resampler are in
|
||||
|
||||
|
|
|
|||
|
|
@ -16,37 +16,6 @@
|
|||
|
||||
constexpr uintptr_t TypeAlignment = 4;
|
||||
|
||||
template <>
|
||||
void sfz::cumsum<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::snippetCumsum(in, out);
|
||||
|
||||
auto mmOutput = _mm_set_ps1(*(out - 1));
|
||||
while (in < lastAligned) {
|
||||
auto mmOffset = _mm_load_ps(in);
|
||||
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, _MM_SHUFFLE(1, 0, 0, 0)));
|
||||
mmOutput = _mm_add_ps(mmOutput, mmOffset);
|
||||
_mm_store_ps(out, mmOutput);
|
||||
mmOutput = _mm_shuffle_ps(mmOutput, mmOutput, _MM_SHUFFLE(3, 3, 3, 3));
|
||||
incrementAll<TypeAlignment>(in, out);
|
||||
}
|
||||
|
||||
while (in < sentinel)
|
||||
_internals::snippetCumsum(in, out);
|
||||
}
|
||||
|
||||
template <>
|
||||
void sfz::diff<float, true>(absl::Span<const float> input, absl::Span<float> output) noexcept
|
||||
{
|
||||
|
|
|
|||
|
|
@ -696,7 +696,8 @@ TEST_CASE("[Helpers] Cumulative sum")
|
|||
std::array<float, 6> input { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f, 1.6f }; // 1.1 2.3 3.6 5.0f 6.5 8.1
|
||||
std::array<float, 6> output;
|
||||
std::array<float, 6> expected { 1.1f, 2.3f, 3.6f, 5.0f, 6.5f, 8.1f };
|
||||
sfz::cumsum<float, false>(input, absl::MakeSpan(output));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, false);
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(output));
|
||||
REQUIRE(approxEqual<float>(output, expected));
|
||||
}
|
||||
|
||||
|
|
@ -707,8 +708,10 @@ TEST_CASE("[Helpers] Cumulative sum (SIMD vs Scalar)")
|
|||
std::vector<float> outputSIMD(bigBufferSize);
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::linearRamp, true);
|
||||
sfz::linearRamp<float>(absl::MakeSpan(input), 0.0f, 0.1f);
|
||||
sfz::cumsum<float, false>(input, absl::MakeSpan(outputScalar));
|
||||
sfz::cumsum<float, true>(input, absl::MakeSpan(outputSIMD));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, false);
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(outputScalar));
|
||||
sfz::setSIMDOpStatus(sfz::SIMDOps::cumsum, true);
|
||||
sfz::cumsum<float>(input, absl::MakeSpan(outputSIMD));
|
||||
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue