Skip to content

Commit

Permalink
Add accessors to Views
Browse files Browse the repository at this point in the history
* Add a new template parameter to View
* Add a new DefaultAccessor, which just passes through the reference

Fixes: #523
  • Loading branch information
bernhardmgruber committed Oct 31, 2022
1 parent 8368c31 commit f6d3bc4
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 33 deletions.
4 changes: 2 additions & 2 deletions include/llama/RecordRef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ namespace llama
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return this->view.accessor(arrayIndex(), AbsolutCoord{});
return this->view.access(arrayIndex(), AbsolutCoord{});
}
}

Expand All @@ -454,7 +454,7 @@ namespace llama
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return this->view.accessor(arrayIndex(), AbsolutCoord{});
return this->view.access(arrayIndex(), AbsolutCoord{});
}
}

Expand Down
78 changes: 48 additions & 30 deletions include/llama/View.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,20 @@

namespace llama
{
/// Default accessor. Passes through the given reference.
struct DefaultAccessor
{
template<typename Reference>
LLAMA_FN_HOST_ACC_INLINE auto operator()(Reference&& r) const -> Reference
{
return std::forward<Reference>(r);
}
};

#ifdef __cpp_lib_concepts
template<typename TMapping, Blob BlobType>
template<typename TMapping, Blob BlobType, typename TAccessor = DefaultAccessor>
#else
template<typename TMapping, typename BlobType>
template<typename TMapping, typename BlobType, typename TAccessor = DefaultAccessor>
#endif
struct View;

Expand Down Expand Up @@ -321,13 +331,15 @@ namespace llama
/// view should be created using \ref allocView.
/// \tparam TMapping The mapping used by the view to map accesses into memory.
/// \tparam BlobType The storage type used by the view holding memory.
/// \tparam TAccessor The accessor to use when an access is made through this view.
#ifdef __cpp_lib_concepts
template<typename TMapping, Blob BlobType>
template<typename TMapping, Blob BlobType, typename TAccessor>
#else
template<typename TMapping, typename BlobType>
template<typename TMapping, typename BlobType, typename TAccessor>
#endif
struct LLAMA_DECLSPEC_EMPTY_BASES View
: private TMapping
, private TAccessor
#if CAN_USE_RANGES
, std::ranges::view_base
#endif
Expand All @@ -337,6 +349,7 @@ namespace llama
using ArrayExtents = typename Mapping::ArrayExtents;
using ArrayIndex = typename Mapping::ArrayIndex;
using RecordDim = typename Mapping::RecordDim;
using Accessor = TAccessor;
using iterator = Iterator<View>;
using const_iterator = Iterator<const View>;
using size_type = typename ArrayExtents::value_type;
Expand Down Expand Up @@ -371,6 +384,16 @@ namespace llama
return static_cast<const Mapping&>(*this);
}

LLAMA_FN_HOST_ACC_INLINE auto accessor() -> Accessor&
{
return static_cast<Accessor&>(*this);
}

LLAMA_FN_HOST_ACC_INLINE auto accessor() const -> const Accessor&
{
return static_cast<const Accessor&>(*this);
}

#if !(defined(_MSC_VER) && defined(__NVCC__))
template<typename V>
auto operator()(llama::ArrayIndex<V, ArrayIndex::rank>) const
Expand All @@ -390,7 +413,7 @@ namespace llama
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor(ai, RecordCoord<>{});
return access(ai, RecordCoord<>{});
}
}

Expand All @@ -404,7 +427,7 @@ namespace llama
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor(ai, RecordCoord<>{});
return access(ai, RecordCoord<>{});
}
}

Expand Down Expand Up @@ -500,15 +523,15 @@ namespace llama
friend struct RecordRef;

template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai, RecordCoord<Coords...> rc = {}) const -> decltype(auto)
LLAMA_FN_HOST_ACC_INLINE auto access(ArrayIndex ai, RecordCoord<Coords...> rc = {}) const -> decltype(auto)
{
return mapToMemory(mapping(), ai, rc, storageBlobs);
return accessor()(mapToMemory(mapping(), ai, rc, storageBlobs));
}

template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai, RecordCoord<Coords...> rc = {}) -> decltype(auto)
LLAMA_FN_HOST_ACC_INLINE auto access(ArrayIndex ai, RecordCoord<Coords...> rc = {}) -> decltype(auto)
{
return mapToMemory(mapping(), ai, rc, storageBlobs);
return accessor()(mapToMemory(mapping(), ai, rc, storageBlobs));
}
};

Expand Down Expand Up @@ -551,6 +574,15 @@ namespace llama
});
}

// Creates a new view from an existing view with the given accessor.
// \param view A view which's mapping and blobs are copied into a new view with the different accessor. If you no
// longer need the old view, consider moving it into the argument of this function.
template<typename NewAccessor, typename Mapping, typename BlobType, typename OldAccessor>
LLAMA_FN_HOST_ACC_INLINE auto withAccessor(View<Mapping, BlobType, OldAccessor> view)
{
return View<Mapping, BlobType, NewAccessor>{std::move(view.mapping()), std::move(view.storageBlobs)};
}

template<typename View>
inline constexpr auto isView = false;

Expand Down Expand Up @@ -578,18 +610,6 @@ namespace llama
{
}

template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai) const -> const auto&
{
return parentView.template accessor<Coords...>(ArrayIndex{ai + offset});
}

template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai) -> auto&
{
return parentView.template accessor<Coords...>(ArrayIndex{ai + offset});
}

/// Same as \ref View::operator()(ArrayIndex), but shifted by the offset of this \ref VirtualView.
LLAMA_FN_HOST_ACC_INLINE auto operator()(ArrayIndex ai) const -> decltype(auto)
{
Expand Down Expand Up @@ -632,18 +652,16 @@ namespace llama
ArrayIndex{ArrayIndex{static_cast<typename ArrayIndex::value_type>(indices)...} + offset});
}

template<std::size_t... Coord>
LLAMA_FN_HOST_ACC_INLINE auto operator()(RecordCoord<Coord...> = {}) const -> decltype(auto)
template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto operator()(RecordCoord<Coords...> rc = {}) const -> decltype(auto)
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor<Coord...>(ArrayIndex{});
return parentView(ArrayIndex{} + offset, rc);
}

template<std::size_t... Coord>
LLAMA_FN_HOST_ACC_INLINE auto operator()(RecordCoord<Coord...> = {}) -> decltype(auto)
template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto operator()(RecordCoord<Coords...> rc = {}) -> decltype(auto)
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor<Coord...>(ArrayIndex{});
return parentView(ArrayIndex{} + offset, rc);
}

StoredParentView parentView;
Expand Down
54 changes: 53 additions & 1 deletion tests/view.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "common.hpp"

#include <atomic>
#include <deque>

// clang-format off
Expand Down Expand Up @@ -85,7 +86,7 @@ TEST_CASE("view.non-memory-owning")
test(boost::mp11::mp_identity<const std::byte>{});
}

TEST_CASE("view.access")
TEST_CASE("view.subscript")
{
using ArrayExtents = llama::ArrayExtentsDynamic<int, 2>;
ArrayExtents extents{16, 16};
Expand Down Expand Up @@ -322,3 +323,54 @@ TEMPLATE_TEST_CASE("view.shallowCopy", "", llama::bloballoc::Vector, llama::blob
auto copyOfCopy = llama::shallowCopy(copy);
checkCopy(view, copyOfCopy);
}

TEMPLATE_TEST_CASE("view.withAccessor.DefaultAccessor", "", llama::bloballoc::Vector, llama::bloballoc::SharedPtr)
{
auto view = llama::allocView(llama::mapping::AoS{llama::ArrayExtents{16, 16}, Particle{}}, TestType{});
auto view2 = llama::withAccessor<llama::DefaultAccessor>(llama::shallowCopy(view));
iotaFillView(view2);
iotaCheckView(view);
}

namespace
{
struct AtomicAccessor
{
template<typename Reference>
LLAMA_FN_HOST_ACC_INLINE auto operator()(Reference&& r) const
{
static_assert(std::is_lvalue_reference_v<Reference>);
return std::atomic_ref{r};
}
};
} // namespace

TEMPLATE_TEST_CASE("view.withAccessor.AtomicAccessor", "", llama::bloballoc::Vector, llama::bloballoc::SharedPtr)
{
auto view = llama::allocView(llama::mapping::AoS{llama::ArrayExtents{16, 16}, Particle{}}, TestType{});
auto view2 = llama::withAccessor<AtomicAccessor>(llama::shallowCopy(view));
iotaFillView(view2);
iotaCheckView(view);
}

namespace
{
struct RestrictedAccessor
{
template<typename Reference>
LLAMA_FN_HOST_ACC_INLINE auto operator()(Reference&& r) const -> __restrict Reference&
{
static_assert(std::is_lvalue_reference_v<Reference>);

return r;
}
};
} // namespace

TEMPLATE_TEST_CASE("view.withAccessor.RestrictedAccessor", "", llama::bloballoc::Vector, llama::bloballoc::SharedPtr)
{
auto view = llama::allocView(llama::mapping::AoS{llama::ArrayExtents{16, 16}, Particle{}}, TestType{});
auto view2 = llama::withAccessor<RestrictedAccessor>(llama::shallowCopy(view));
iotaFillView(view2);
iotaCheckView(view);
}

0 comments on commit f6d3bc4

Please sign in to comment.