Skip to content

Commit

Permalink
support sub arrays of dynamic size as field type
Browse files Browse the repository at this point in the history
* allow dynamic field types in the record dimension
* add specializations to most of the core functions
* add llama::dynamic to signal a dynamic array member in a RecordCoord
* extend VirtualRecord to allow holding dynamic indices
* extend blobNrAndOffset to allow for additional dynamic indices
* add OffsetTable mapping
* add customization allowing to dump OffsetTable mappings
* add a few unit tests
  • Loading branch information
bernhardmgruber committed Dec 3, 2021
1 parent 0b7611f commit 2b4b65b
Show file tree
Hide file tree
Showing 25 changed files with 876 additions and 76 deletions.
8 changes: 5 additions & 3 deletions examples/bufferguard/bufferguard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ struct GuardMapping2D : llama::ArrayExtentsDynamic<2>
std::abort();
}

template<std::size_t... RecordCoords>
constexpr auto blobNrAndOffset(ArrayIndex ai, llama::RecordCoord<RecordCoords...> rc = {}) const
-> llama::NrAndOffset
template<std::size_t... RecordCoords, std::size_t N = 0>
constexpr auto blobNrAndOffset(
ArrayIndex ai,
llama::Array<std::size_t, N> = {},
llama::RecordCoord<RecordCoords...> rc = {}) const -> llama::NrAndOffset
{
// [0][0] is at left top
const auto [row, col] = ai;
Expand Down
2 changes: 1 addition & 1 deletion include/llama/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ namespace llama
{ m.blobSize(std::size_t{}) } -> std::same_as<std::size_t>;
{ m.blobNrAndOffset(typename M::ArrayIndex{}) } -> std::same_as<NrAndOffset>;
{ m.template blobNrAndOffset<0>(typename M::ArrayIndex{}) } -> std::same_as<NrAndOffset>;
{ m.blobNrAndOffset(typename M::ArrayIndex{}, llama::RecordCoord<0>{}) } -> std::same_as<NrAndOffset>;
{ m.blobNrAndOffset(typename M::ArrayIndex{}, {}, llama::RecordCoord<0>{}) } -> std::same_as<NrAndOffset>;
};
// clang-format on

Expand Down
53 changes: 53 additions & 0 deletions include/llama/Core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ namespace llama
template<typename T>
inline constexpr bool isAllowedFieldType = std::is_trivially_destructible_v<T>;

template<typename... Fields>
inline constexpr bool isAllowedFieldType<Record<Fields...>> = true;

template<typename T, std::size_t N>
inline constexpr bool isAllowedFieldType<T[N]> = isAllowedFieldType<T>;

template<typename T>
inline constexpr bool isAllowedFieldType<T[]> = isAllowedFieldType<T>;

/// Record dimension tree node which may either be a leaf or refer to a child tree presented as another \ref
/// Record.
/// \tparam Tag Name of the node. May be any type (struct, class).
Expand Down Expand Up @@ -101,6 +110,14 @@ namespace llama
= boost::mp11::mp_push_front<typename GetTagsImpl<ChildType, RecordCoord<Coords...>>::type, ChildTag>;
};

template<typename ChildType, std::size_t... Coords>
struct GetTagsImpl<ChildType[], RecordCoord<dynamic, Coords...>>
{
using ChildTag = RecordCoord<dynamic>;
using type
= boost::mp11::mp_push_front<typename GetTagsImpl<ChildType, RecordCoord<Coords...>>::type, ChildTag>;
};

template<typename T>
struct GetTagsImpl<T, RecordCoord<>>
{
Expand Down Expand Up @@ -198,6 +215,16 @@ namespace llama
typename GetCoordFromTagsImpl<ChildType, RecordCoord<ResultCoords..., FirstTag::front>, Tags...>::type;
};

template<typename ChildType, std::size_t... ResultCoords, typename FirstTag, typename... Tags>
struct GetCoordFromTagsImpl<ChildType[], RecordCoord<ResultCoords...>, FirstTag, Tags...>
{
static_assert(
std::is_same_v<FirstTag, RecordCoord<dynamic>>,
"Please use a RecordCoord<dynamic> to index into dynamic arrays");
using type =
typename GetCoordFromTagsImpl<ChildType, RecordCoord<ResultCoords..., FirstTag::front>, Tags...>::type;
};

template<typename RecordDim, typename RecordCoord>
struct GetCoordFromTagsImpl<RecordDim, RecordCoord>
{
Expand Down Expand Up @@ -242,6 +269,13 @@ namespace llama
using type = typename GetTypeImpl<ChildType, RecordCoord<TailCoords...>>::type;
};

template<typename ChildType, std::size_t HeadCoord, std::size_t... TailCoords>
struct GetTypeImpl<ChildType[], RecordCoord<HeadCoord, TailCoords...>>
{
static_assert(HeadCoord == dynamic, "Record coord at a dynamic array must be llama::dynamic");
using type = typename GetTypeImpl<ChildType, RecordCoord<TailCoords...>>::type;
};

template<typename T>
struct GetTypeImpl<T, RecordCoord<>>
{
Expand Down Expand Up @@ -289,6 +323,12 @@ namespace llama
}
using type = decltype(help(std::make_index_sequence<N>{}));
};

template<typename Child, std::size_t... RCs>
struct LeafRecordCoordsImpl<Child[], RecordCoord<RCs...>>
{
using type = typename LeafRecordCoordsImpl<Child, RecordCoord<RCs..., dynamic>>::type;
};
} // namespace internal

/// Returns a flat type list containing all record coordinates to all leaves of the given record dimension.
Expand Down Expand Up @@ -557,6 +597,19 @@ namespace llama
struct IsBoundedArray<T[N]> : std::true_type
{
};

template<class T>
struct is_unbounded_array : std::false_type
{
};

template<class T>
struct is_unbounded_array<T[]> : std::true_type
{
};

template<typename T>
inline constexpr bool is_unbounded_array_v = is_unbounded_array<T>::value;
} // namespace internal

namespace internal
Expand Down
22 changes: 21 additions & 1 deletion include/llama/DumpMapping.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "ArrayIndexRange.hpp"
#include "Core.hpp"
#include "mapping/OffsetTable.hpp"

#include <boost/functional/hash.hpp>
#include <fmt/format.h>
Expand Down Expand Up @@ -75,14 +76,33 @@ namespace llama
{ai,
internal::toVec(rc),
recordCoordTags<RecordDim>(rc),
mapping.blobNrAndOffset(ai, rc),
mapping.blobNrAndOffset(ai, {}, rc),
sizeof(GetType<RecordDim, decltype(rc)>)});
});
}

return infos;
}

template<typename ArrayExtents, typename RecordDim, typename SubMappings>
auto boxesFromMapping(const mapping::OffsetTable<ArrayExtents, RecordDim, SubMappings>& mapping)
-> std::vector<FieldBox<ArrayExtents::rank>>
{
std::size_t previousBlobs = 0;
std::vector<FieldBox<ArrayExtents::rank>> infos;
boost::mp11::mp_for_each<boost::mp11::mp_iota<boost::mp11::mp_size<decltype(mapping.subMappings)>>>(
[&](auto ic)
{
const auto& subMapping = get<decltype(ic)::value>(mapping.subMappings);
auto subBoxes = boxesFromMapping(subMapping);
for(auto& box : subBoxes)
box.nrAndOffset.nr += previousBlobs;
infos.insert(infos.end(), subBoxes.begin(), subBoxes.end());
previousBlobs += std::decay_t<decltype(subMapping)>::blobCount;
});
return infos;
}

template<std::size_t Dim>
auto breakBoxes(std::vector<FieldBox<Dim>> boxes, std::size_t wrapByteCount) -> std::vector<FieldBox<Dim>>
{
Expand Down
6 changes: 4 additions & 2 deletions include/llama/Proofs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ namespace llama
{
using Type
= GetType<typename Mapping::RecordDim, decltype(rc)>;
const auto [blob, offset] = m.blobNrAndOffset(ai, rc);
const auto [blob, offset]
= m.blobNrAndOffset(ai, {}, rc);
for(std::size_t b = 0; b < sizeof(Type); b++)
if(testAndSet(blob, offset + b))
{
Expand Down Expand Up @@ -105,7 +106,8 @@ namespace llama
{
using Type
= GetType<typename Mapping::RecordDim, decltype(rc)>;
const auto [blob, offset] = m.blobNrAndOffset(ai, rc);
const auto [blob, offset]
= m.blobNrAndOffset(ai, {}, rc);
if(flatIndex % PieceLength != 0
&& (lastBlob != blob
|| lastOffset + sizeof(Type) != offset))
Expand Down
3 changes: 3 additions & 0 deletions include/llama/RecordCoord.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
#include "Meta.hpp"

#include <array>
#include <limits>
#include <ostream>
#include <type_traits>

namespace llama
{
inline constexpr auto dynamic = std::numeric_limits<std::size_t>::max();

/// Represents a coordinate for a record inside the record dimension tree.
/// \tparam Coords... the compile time coordinate.
template<std::size_t... Coords>
Expand Down
28 changes: 17 additions & 11 deletions include/llama/View.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,12 @@ namespace llama
if constexpr(isRecord<RecordDim> || internal::IsBoundedArray<RecordDim>::value)
{
LLAMA_FORCE_INLINE_RECURSIVE
return VirtualRecord<const View>{ai, *this};
return VirtualRecord<const View>{*this, ai};
}
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor(ai, RecordCoord<>{});
return accessor(ai, Array<size_t, 0>{}, RecordCoord<>{});
}
}

Expand All @@ -356,12 +356,12 @@ namespace llama
if constexpr(isRecord<RecordDim> || internal::IsBoundedArray<RecordDim>::value)
{
LLAMA_FORCE_INLINE_RECURSIVE
return VirtualRecord<View>{ai, *this};
return VirtualRecord<View>{*this, ai};
}
else
{
LLAMA_FORCE_INLINE_RECURSIVE
return accessor(ai, RecordCoord<>{});
return accessor(ai, Array<size_t, 0>{}, RecordCoord<>{});
}
}

Expand Down Expand Up @@ -451,28 +451,34 @@ namespace llama
friend struct VirtualRecord;

LLAMA_SUPPRESS_HOST_DEVICE_WARNING
template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai, RecordCoord<Coords...> rc = {}) const -> decltype(auto)
template<std::size_t N, std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(
ArrayIndex ai,
Array<size_t, N> dynamicArrayExtents,
RecordCoord<Coords...> rc = {}) const -> decltype(auto)
{
if constexpr(llama::isComputed<Mapping, RecordCoord<Coords...>>)
return mapping().compute(ai, rc, storageBlobs);
else
{
const auto [nr, offset] = mapping().blobNrAndOffset(ai, rc);
const auto [nr, offset] = mapping().blobNrAndOffset(ai, dynamicArrayExtents, rc);
using Type = GetType<RecordDim, RecordCoord<Coords...>>;
return reinterpret_cast<const Type&>(storageBlobs[nr][offset]);
}
}

LLAMA_SUPPRESS_HOST_DEVICE_WARNING
template<std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(ArrayIndex ai, RecordCoord<Coords...> rc = {}) -> decltype(auto)
template<std::size_t N, std::size_t... Coords>
LLAMA_FN_HOST_ACC_INLINE auto accessor(
ArrayIndex ai,
Array<size_t, N> dynamicArrayExtents,
RecordCoord<Coords...> rc = {}) -> decltype(auto)
{
if constexpr(llama::isComputed<Mapping, RecordCoord<Coords...>>)
return mapping().compute(ai, rc, storageBlobs);
return mapping().compute(ai, dynamicArrayExtents, rc, storageBlobs);
else
{
const auto [nr, offset] = mapping().blobNrAndOffset(ai, rc);
const auto [nr, offset] = mapping().blobNrAndOffset(ai, dynamicArrayExtents, rc);
using Type = GetType<RecordDim, RecordCoord<Coords...>>;
using QualifiedType = std::conditional_t<
std::is_const_v<std::remove_reference_t<decltype(storageBlobs[nr][offset])>>,
Expand Down
Loading

0 comments on commit 2b4b65b

Please sign in to comment.