Low-Level Abstraction of Memory Access
Split.hpp
Go to the documentation of this file.
1 // Copyright 2022 Bernhard Manfred Gruber
2 // SPDX-License-Identifier: MPL-2.0
3 
4 #pragma once
5 
6 #include "../View.hpp"
7 #include "Common.hpp"
8 
9 namespace llama::mapping
10 {
11  namespace internal
12  {
13  template<typename... Fields, std::size_t FirstCoord, std::size_t... Coords>
15  {
16  using Rec = Record<Fields...>;
17  if constexpr(sizeof...(Coords) == 0)
18  {
19  using Part1 = Record<mp_at_c<Rec, FirstCoord>>;
20  using Part2 = mp_erase_c<Rec, FirstCoord, FirstCoord + 1>;
21  return mp_list<Part1, Part2>{};
22  }
23  else
24  {
25  using FieldTag = GetTag<Rec, RecordCoord<FirstCoord>>;
26  using FieldType = GetType<Rec, RecordCoord<FirstCoord>>;
27  using InnerPartition = decltype(partitionRecordDim(FieldType{}, RecordCoord<Coords...>{}));
29  using Part2 = mp_replace_at_c<Rec, FirstCoord, Field<FieldTag, mp_second<InnerPartition>>>;
30  return mp_list<Part1, Part2>{};
31  }
32  }
33 
34  template<typename Acc, typename TagList>
36  {
37  using Part1Before = mp_first<Acc>;
38  using Part2Before = mp_second<Acc>;
40  using Part1After = mp_first<R>;
41  using Part2After = mp_second<R>;
42 
43  using type = mp_list<MergedRecordDims<Part1Before, Part1After>, Part2After>;
44  };
45 
46  template<typename Acc, typename TagList>
48 
49  template<typename... Fields, typename... RCs>
50  auto partitionRecordDim(Record<Fields...>, mp_list<RCs...>)
51  {
52  static_assert((isRecordCoord<RCs> && ...));
53  using Initial = mp_list<Record<>, Record<Fields...>>; // initially, nothing selected for mapping 1
54  return mp_fold<mp_list<GetTags<Record<Fields...>, RCs>...>, Initial, PartitionFoldOp>{};
55  }
56 
57  template<typename RC, typename RecordCoordForMapping1>
58  inline constexpr bool isSelected = recordCoordCommonPrefixIsSame<RecordCoordForMapping1, RC>;
59 
60  template<typename RC, typename... RecordCoordsForMapping1>
61  inline constexpr bool isSelected<RC, mp_list<RecordCoordsForMapping1...>>
62  = (isSelected<RC, RecordCoordsForMapping1> || ...);
63 
64  template<typename RecordDim, typename Selector>
66 
67  template<typename RecordDim, std::size_t... RCs>
68  struct ReplaceTagListsByCoords<RecordDim, RecordCoord<RCs...>>
69  {
70  using type = RecordCoord<RCs...>;
71  };
72 
73  template<typename RecordDim, typename... Args>
74  struct ReplaceTagListsByCoords<RecordDim, mp_list<Args...>>
75  {
76  static auto f()
77  {
78  if constexpr(((mp_is_list<Args>::value || isRecordCoord<Args>) &&...))
79  // Args is a pack of tag lists/record coords
80  return mp_list<GetCoordFromTags<RecordDim, Args>...>{};
81  else
82  // Args is a single tag lists
83  return GetCoordFromTags<RecordDim, Args...>{};
84  }
85 
86  using type = decltype(f());
87  };
88  } // namespace internal
89 
98  template<
99  typename TArrayExtents,
100  typename TRecordDim,
101  typename TSelectorForMapping1,
102  template<typename...>
103  typename MappingTemplate1,
104  template<typename...>
105  typename MappingTemplate2,
106  bool SeparateBlobs = false>
107  struct Split
108  {
109  static_assert(isRecord<TRecordDim>, "Cannot split a scalar record dim");
110 
111  using ArrayExtents = TArrayExtents;
112  using ArrayIndex = typename ArrayExtents::Index;
113  using RecordDim = TRecordDim;
114 
115  using SelectorForMapping1 = TSelectorForMapping1;
120  using RecordDim1 = mp_first<RecordDimPartitions>;
121  using RecordDim2 = mp_second<RecordDimPartitions>;
122 
123  using Mapping1 = MappingTemplate1<ArrayExtents, RecordDim1>;
124  using Mapping2 = MappingTemplate2<ArrayExtents, RecordDim2>;
125 
126  static constexpr std::size_t blobCount = SeparateBlobs ? Mapping1::blobCount + Mapping2::blobCount : 1;
127  static_assert(SeparateBlobs || Mapping1::blobCount == 1);
128  static_assert(SeparateBlobs || Mapping2::blobCount == 1);
129 
130  private:
131  using size_type = typename ArrayExtents::value_type;
132  static constexpr size_type m1bc = static_cast<size_type>(Mapping1::blobCount);
133 
134  public:
135  constexpr Split() = default;
136 
139  {
140  }
141 
144  : mapping1(std::move(mapping1))
145  , mapping2(std::move(mapping2))
146  {
147  }
148 
149  template<typename... Args1, typename... Args2>
150  LLAMA_FN_HOST_ACC_INLINE constexpr Split(std::tuple<Args1...> mappingArgs1, std::tuple<Args2...> mappingArgs2)
151  : mapping1(std::make_from_tuple<Mapping1>(mappingArgs1))
152  , mapping2(std::make_from_tuple<Mapping2>(mappingArgs2))
153  {
154  }
155 
157  {
158  return mapping1.extents();
159  }
160 
161  LLAMA_FN_HOST_ACC_INLINE constexpr auto blobSize([[maybe_unused]] size_type i) const -> size_type
162  {
163  if constexpr(SeparateBlobs)
164  {
165  if(i < m1bc)
166  return mapping1.blobSize(i);
167  return mapping2.blobSize(i - m1bc);
168  }
169  else
170  return mapping1.blobSize(0) + mapping2.blobSize(0);
171  }
172 
173  template<std::size_t... RecordCoords>
176  {
177  using Tags = GetTags<RecordDim, RecordCoord<RecordCoords...>>;
178 
181  else
182  {
183  auto nrAndOffset = mapping2.blobNrAndOffset(ai, GetCoordFromTags<RecordDim2, Tags>{});
184  if constexpr(SeparateBlobs)
185  nrAndOffset.nr += m1bc;
186  else
187  {
188  for(size_type i = 0; i < m1bc; i++)
189  nrAndOffset.offset += mapping1.blobSize(i);
190  }
191  return nrAndOffset;
192  }
193  }
194 
195  template<std::size_t... RecordCoords>
196  static constexpr auto isComputed(RecordCoord<RecordCoords...>) -> bool
197  {
198  using Tags = GetTags<RecordDim, RecordCoord<RecordCoords...>>;
200  return llama::isComputed<Mapping1, GetCoordFromTags<RecordDim1, Tags>>;
201  else
202  return llama::isComputed<Mapping2, GetCoordFromTags<RecordDim2, Tags>>;
203  }
204 
205  template<std::size_t... RecordCoords, typename Blobs>
207  const
208  {
209  using Tags = GetTags<RecordDim, RecordCoord<RecordCoords...>>;
211  return mapping1.compute(ai, GetCoordFromTags<RecordDim1, Tags>{}, blobs);
212  else
213  {
214  // only pass on blobs for mapping 2, so it can index starting from 0
215  auto* blobs2 = &blobs[0] + m1bc;
216  return mapping2.compute(ai, GetCoordFromTags<RecordDim2, Tags>{}, blobs2);
217  }
218  }
219 
222  };
223 
227  template<
228  typename SelectorForMapping1,
229  template<typename...>
230  typename MappingTemplate1,
231  template<typename...>
232  typename MappingTemplate2,
233  bool SeparateBlobs = false>
234  struct BindSplit
235  {
236  template<typename ArrayExtents, typename RecordDim>
237  using fn
239  };
240 
242  template<typename Mapping>
243  inline constexpr bool isSplit = false;
244 
246  template<
247  typename ArrayExtents,
248  typename RecordDim,
249  typename SelectorForMapping1,
250  template<typename...>
251  typename MappingTemplate1,
252  template<typename...>
253  typename MappingTemplate2,
254  bool SeparateBlobs>
255  inline constexpr bool
256  isSplit<Split<ArrayExtents, RecordDim, SelectorForMapping1, MappingTemplate1, MappingTemplate2, SeparateBlobs>>
257  = true;
258 } // namespace llama::mapping
#define LLAMA_EXPORT
Definition: macros.hpp:192
#define LLAMA_FN_HOST_ACC_INLINE
Definition: macros.hpp:96
typename PartitionFoldOpImpl< Acc, TagList >::type PartitionFoldOp
Definition: Split.hpp:47
auto partitionRecordDim(Record< Fields... >, RecordCoord< FirstCoord, Coords... >)
Definition: Split.hpp:14
constexpr bool isSelected
Definition: Split.hpp:58
constexpr bool isSplit
Definition: Split.hpp:243
ArrayExtents(Args...) -> ArrayExtents< typename internal::IndexTypeFromArgs< std::size_t, Args... >::type,(Args{}, dyn)... >
typename internal::GetTagsImpl< RecordDim, RecordCoord >::type GetTags
Definition: Core.hpp:233
typename internal::GetTagImpl< RecordDim, RecordCoord >::type GetTag
Get the tag of the Field at a RecordCoord inside the record dimension tree.
Definition: Core.hpp:253
typename internal::GetCoordFromTagsImpl< RecordDim, RecordCoord<>, TagsOrTagList... >::type GetCoordFromTags
Definition: Core.hpp:353
typename internal::GetTypeImpl< RecordDim, RecordCoordOrTags... >::type GetType
Definition: Core.hpp:388
ArrayIndex< T, rank > Index
A type list of Fields which may be used to define a record dimension.
Definition: Core.hpp:61
TArrayExtents ArrayExtents
Definition: Split.hpp:111
static constexpr std::size_t blobCount
Definition: Split.hpp:126
mp_first< RecordDimPartitions > RecordDim1
Definition: Split.hpp:120
typename ArrayExtents::Index ArrayIndex
Definition: Split.hpp:112
constexpr Split()=default
constexpr auto blobNrAndOffset(ArrayIndex ai, RecordCoord< RecordCoords... >={}) const -> NrAndOffset< size_type >
Definition: Split.hpp:174
decltype(internal::partitionRecordDim(RecordDim{}, NormalizedSelectorForMapping1{})) RecordDimPartitions
Definition: Split.hpp:119
MappingTemplate2< ArrayExtents, RecordDim2 > Mapping2
Definition: Split.hpp:124
TSelectorForMapping1 SelectorForMapping1
Definition: Split.hpp:115
typename internal::ReplaceTagListsByCoords< RecordDim, SelectorForMapping1 >::type NormalizedSelectorForMapping1
Definition: Split.hpp:117
constexpr Split(ArrayExtents extents)
Definition: Split.hpp:138
constexpr Split(Mapping1 mapping1, Mapping2 mapping2)
Definition: Split.hpp:143
constexpr auto extents() const -> ArrayExtents
Definition: Split.hpp:156
constexpr auto blobSize([[maybe_unused]] size_type i) const -> size_type
Definition: Split.hpp:161
MappingTemplate1< ArrayExtents, RecordDim1 > Mapping1
Definition: Split.hpp:123
TRecordDim RecordDim
Definition: Split.hpp:113
mp_second< RecordDimPartitions > RecordDim2
Definition: Split.hpp:121
constexpr Split(std::tuple< Args1... > mappingArgs1, std::tuple< Args2... > mappingArgs2)
Definition: Split.hpp:150
static constexpr auto isComputed(RecordCoord< RecordCoords... >) -> bool
Definition: Split.hpp:196
constexpr auto compute(ArrayIndex ai, RecordCoord< RecordCoords... >, Blobs &blobs) const
Definition: Split.hpp:206
mp_list< MergedRecordDims< Part1Before, Part1After >, Part2After > type
Definition: Split.hpp:43
decltype(partitionRecordDim(Part2Before{}, GetCoordFromTags< Part2Before, TagList >{})) R
Definition: Split.hpp:39