Skip to content

Commit

Permalink
migrate simdForEach facebook#2: remove unroll step
Browse files Browse the repository at this point in the history
Summary: detail::UnrollStep should go away, because otherwise it would be exposed to the user of `simdForEach`.

Reviewed By: yfeldblum

Differential Revision: D60587842
  • Loading branch information
DenisYaroshevskiy authored and facebook-github-bot committed Aug 6, 2024
1 parent 53bd909 commit bd5fd29
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 43 deletions.
1 change: 1 addition & 0 deletions folly/algorithm/simd/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ cpp_library(
headers = ["SimdForEach.h"],
exported_deps = [
"//folly:c_portability",
"//folly:traits",
"//folly/algorithm/simd/detail:unroll_utils",
],
)
25 changes: 11 additions & 14 deletions folly/algorithm/simd/SimdForEach.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#pragma once

#include <folly/CPortability.h>
#include <folly/Traits.h>
#include <folly/algorithm/simd/detail/UnrollUtils.h>

#include <array>
Expand Down Expand Up @@ -110,10 +111,9 @@ FOLLY_ALWAYS_INLINE T* previousAlignedAddress(T* ptr, int to) {
struct SimdForEachMainLoop {
template <typename T, typename Delegate>
FOLLY_ALWAYS_INLINE bool operator()(
int cardinal, T*& f, T* l, Delegate& delegate, detail::UnrollStep<1>)
const {
int cardinal, T*& f, T* l, Delegate& delegate, index_constant<1>) const {
while (f != l) {
if (delegate.step(f, ignore_none{}, detail::UnrollStep<0>{}))
if (delegate.step(f, ignore_none{}, index_constant<0>{}))
return true;
f += cardinal;
}
Expand All @@ -129,8 +129,8 @@ struct SimdForEachMainLoop {
T* l;
Delegate& delegate;

template <int i>
FOLLY_ALWAYS_INLINE bool operator()(detail::UnrollStep<i> unrollI) {
template <std::size_t i>
FOLLY_ALWAYS_INLINE bool operator()(index_constant<i> unrollI) {
if (f == l)
return true;

Expand All @@ -140,13 +140,10 @@ struct SimdForEachMainLoop {
}
};

template <typename T, typename Delegate, int unrolling>
template <typename T, typename Delegate, std::size_t unrolling>
FOLLY_ALWAYS_INLINE bool operator()(
int cardinal,
T*& f,
T* l,
Delegate& delegate,
detail::UnrollStep<unrolling>) const {
int cardinal, T*& f, T* l, Delegate& delegate, index_constant<unrolling>)
const {
// Not enough to fully unroll explanation.
//
// There are a few approaches to handle this:
Expand Down Expand Up @@ -206,14 +203,14 @@ FOLLY_ALWAYS_INLINE void simdForEachAligning(
ignore_extrema ignore{static_cast<int>(f - af), 0};
if (af != al) {
// first chunk
if (delegate.step(af, ignore, detail::UnrollStep<0>{})) {
if (delegate.step(af, ignore, index_constant<0>{})) {
return;
}
ignore.first = 0;
af += cardinal;

if (SimdForEachMainLoop{}(
cardinal, af, al, delegate, detail::UnrollStep<unrolling>{})) {
cardinal, af, al, delegate, index_constant<unrolling>{})) {
return;
}

Expand All @@ -224,7 +221,7 @@ FOLLY_ALWAYS_INLINE void simdForEachAligning(
}

ignore.last = static_cast<int>(af + cardinal - l);
delegate.step(af, ignore, detail::UnrollStep<0>{});
delegate.step(af, ignore, index_constant<0>{});
}

} // namespace simd_detail
Expand Down
1 change: 1 addition & 0 deletions folly/algorithm/simd/detail/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ cpp_library(
headers = ["UnrollUtils.h"],
exported_deps = [
"//folly:portability",
"//folly:traits",
],
)
32 changes: 12 additions & 20 deletions folly/algorithm/simd/detail/UnrollUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@
#pragma once

#include <folly/Portability.h>
#include <folly/Traits.h>

#include <array>
#include <type_traits>

namespace folly {
namespace detail {

template <int i>
struct UnrollStep : std::integral_constant<int, i> {};
namespace folly::detail {

/**
* UnrollUtils
Expand Down Expand Up @@ -67,13 +65,14 @@ struct UnrollUtils {
* unrollUntil<N>(op)
*
* Do operation N times or until it returns true to break.
* Op accepts UnrollStep<i> so it can keep track of a step begin executed.
* Op accepts integral_constant<i> so it can keep track of a step begin
* executed.
*
* Returns wether true if it was interrupted (you can know if the op breaked)
*/
template <int N, typename Op>
template <std::size_t N, typename Op>
FOLLY_ALWAYS_INLINE static constexpr bool unrollUntil(Op op) {
return unrollUntilImpl<N, 0>(op);
return unrollUntilImpl(op, std::make_index_sequence<N>{});
}

private:
Expand Down Expand Up @@ -117,18 +116,11 @@ struct UnrollUtils {
return op(leftSum, rightSum);
}

template <int N, int i, typename Op>
FOLLY_ALWAYS_INLINE static constexpr std::enable_if_t<i == N, bool>
unrollUntilImpl(Op) {
return false;
}

template <int N, int i, typename Op>
FOLLY_ALWAYS_INLINE static constexpr std::enable_if_t<i != N, bool>
unrollUntilImpl(Op op) {
return op(UnrollStep<i>{}) || unrollUntilImpl<N, i + 1>(op);
template <typename Op, std::size_t... i>
FOLLY_ALWAYS_INLINE static constexpr bool unrollUntilImpl(
Op op, std::index_sequence<i...>) {
return (... || op(index_constant<i>{}));
}
};

} // namespace detail
} // namespace folly
} // namespace folly::detail
22 changes: 14 additions & 8 deletions folly/algorithm/simd/detail/test/UnrollUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,26 @@ TEST(UnrollUtilsTest, ArrayReduce) {
static_assert(10 == reduceValues<1, 2, 3, 4>(), "");
}

template <int stopAt>
template <std::size_t stopAt>
struct UnrollUntilTestOp {
int* lastStep;
std::size_t* lastStep;

template <int i>
constexpr bool operator()(UnrollStep<i>) const {
template <std::size_t i>
constexpr bool operator()(folly::index_constant<i>) const {
*lastStep = i;
return i == stopAt;
}
};

template <int N, int stopAt, bool expectedRes, int expectedLastStep>
constexpr std::size_t kNoStop = std::numeric_limits<std::size_t>::max();

template <
std::size_t N,
std::size_t stopAt,
bool expectedRes,
std::size_t expectedLastStep>
constexpr bool unrollUntilTest() {
int lastStep = -1;
std::size_t lastStep = kNoStop;
UnrollUntilTestOp<stopAt> op{&lastStep};
bool res = UnrollUtils::unrollUntil<N>(op);

Expand All @@ -77,14 +83,14 @@ TEST(UnrollUtilsTest, UnrollUntil) {
/*N*/ 0,
/*stopAt*/ 0,
/*expectedRes*/ false,
/*ExpectedLastStep*/ -1>(),
/*ExpectedLastStep*/ kNoStop>(),
"");
static_assert(
unrollUntilTest<
/*N*/ 0,
/*stopAt*/ 1,
/*expectedRes*/ false,
/*ExpectedLastStep*/ -1>(),
/*ExpectedLastStep*/ kNoStop>(),
"");
static_assert(
unrollUntilTest<
Expand Down
2 changes: 1 addition & 1 deletion folly/algorithm/simd/test/SimdForEachTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct TestDelegate {
return step(
unrolled[unrollI()],
ignore_none{},
detail::UnrollStep<decltype(unrollI)::value + ('A' - 'a')>{});
folly::index_constant<decltype(unrollI)::value + ('A' - 'a')>{});
});
}
};
Expand Down

0 comments on commit bd5fd29

Please sign in to comment.