YOrch 1.0.0
Loading...
Searching...
No Matches
layout.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <array>
4#include <cstddef>
5#include <tuple>
6#include <type_traits>
7#include <utility>
8
9#include "../../slots/policies.hpp"
10#include "erased_slot.hpp"
11#include "policy.hpp"
12#include "typed_slot.hpp"
13
14namespace yorch::detail {
15
23template <typename Plan, std::size_t... I>
24[[nodiscard]] consteval auto make_payload_node_array(std::index_sequence<I...>) {
25 return std::array<bool, sizeof...(I)> {
27 };
28}
29
38template <typename Plan, std::size_t... I>
39[[nodiscard]] consteval auto make_slot_logical_policy_array(std::index_sequence<I...>) {
40 return std::array<slot_logical_policy, sizeof...(I)> {
41 Plan::template slot_logical_policy_for<I>...
42 };
43}
44
45template <typename Plan>
46inline constexpr auto payload_node_array_v =
47 make_payload_node_array<Plan>(std::make_index_sequence<Plan::node_count> {});
48
49template <typename Plan>
50inline constexpr auto slot_logical_policy_array_v =
51 make_slot_logical_policy_array<Plan>(std::make_index_sequence<Plan::node_count> {});
52
53template <typename Plan>
54inline constexpr std::size_t payload_node_count_v = [] {
55 std::size_t count = 0;
56 for (const bool payload : payload_node_array_v<Plan>) {
57 if (payload) {
58 ++count;
59 }
60 }
61 return count;
62}();
63
71template <typename Plan>
73 std::array<std::size_t, Plan::node_count> indices {};
74 indices.fill(no_physical_slot);
75
76 std::size_t next = 0;
77 for (std::size_t node = 0; node < Plan::node_count; ++node) {
79 indices[node] = next++;
80 }
81 }
82
83 return indices;
84}
85
89template <typename Plan>
91 // Node -> physical slot mapping; non-owned nodes keep `no_physical_slot`.
92 std::array<std::size_t, Plan::node_count> physical_slot_indices {};
93 // Payload depth along each node's root-to-node path, including the node.
94 std::array<std::size_t, Plan::node_count> payload_depths {};
95 // Total physical slots needed, equal to the maximum payload depth.
96 std::size_t physical_slot_count = 0;
97};
98
122template <typename Plan>
126
127 for (std::size_t node = 0; node < Plan::node_count; ++node) {
128 const auto parent = Plan::parent_indices[node];
129 const auto parent_depth =
130 parent == Plan::no_parent ? 0 : layout.payload_depths[parent];
131 layout.payload_depths[node] =
132 parent_depth + (payload_node_array_v<Plan>[node] ? 1U : 0U);
133
134 if (payload_node_array_v<Plan>[node]) {
135 layout.physical_slot_indices[node] = layout.payload_depths[node] - 1;
136 if (layout.payload_depths[node] > layout.physical_slot_count) {
137 layout.physical_slot_count = layout.payload_depths[node];
138 }
139 }
140 }
141
142 return layout;
143}
144
176
191template <typename Plan, std::size_t PhysicalSlotCount, std::size_t... I>
193 const std::array<std::size_t, Plan::node_count>& indices,
194 std::index_sequence<I...>) {
195 std::array<std::size_t, PhysicalSlotCount> sizes {};
196 ([&] {
197 if constexpr (!std::is_void_v<typename Plan::template output_type<I>>) {
198 const auto slot = indices[I];
199 if (slot != no_physical_slot) {
200 sizes[slot] = sizes[slot] < sizeof(typename Plan::template output_type<I>)
201 ? sizeof(typename Plan::template output_type<I>)
202 : sizes[slot];
203 }
204 }
205 }(), ...);
206 return sizes;
207}
208
222template <typename Plan, std::size_t PhysicalSlotCount, std::size_t... I>
224 const std::array<std::size_t, Plan::node_count>& indices,
225 std::index_sequence<I...>) {
226 std::array<std::size_t, PhysicalSlotCount> alignments {};
227 ([&] {
228 if constexpr (!std::is_void_v<typename Plan::template output_type<I>>) {
229 const auto slot = indices[I];
230 if (slot != no_physical_slot) {
231 alignments[slot] = alignments[slot] < alignof(typename Plan::template output_type<I>)
232 ? alignof(typename Plan::template output_type<I>)
233 : alignments[slot];
234 }
235 }
236 }(), ...);
237 return alignments;
238}
239
255template <typename Plan, std::size_t PhysicalSlotCount, std::size_t... I>
257 const std::array<std::size_t, Plan::node_count>& indices,
258 std::index_sequence<I...>) {
259 std::array<slot_physical_policy, PhysicalSlotCount> policies {};
261 (((indices[I] != no_physical_slot)
263 policies[indices[I]],
264 Plan::template slot_logical_policy_for<I>)
266 ...);
267 return policies;
268}
269
270template <typename Plan, typename LayoutPolicy>
272
273template <typename Plan>
275 static constexpr auto physical_slot_indices =
277 static constexpr std::size_t physical_slot_count = payload_node_count_v<Plan>;
278 static constexpr auto physical_slot_sizes =
280 physical_slot_indices,
281 std::make_index_sequence<Plan::node_count> {});
282 static constexpr auto physical_slot_alignments =
284 physical_slot_indices,
285 std::make_index_sequence<Plan::node_count> {});
286 static constexpr auto physical_slot_policies =
288 physical_slot_indices,
289 std::make_index_sequence<Plan::node_count> {});
290
291 template <std::size_t I>
292 static constexpr std::size_t physical_slot_index = physical_slot_indices[I];
293
294 template <std::size_t K>
295 static constexpr slot_physical_policy physical_slot_policy = physical_slot_policies[K];
296};
297
298template <typename Plan>
300 static constexpr auto compact_layout =
302 static constexpr auto physical_slot_indices = compact_layout.physical_slot_indices;
303 static constexpr auto payload_depths = compact_layout.payload_depths;
304 static constexpr std::size_t physical_slot_count = compact_layout.physical_slot_count;
305 static constexpr auto physical_slot_sizes =
307 physical_slot_indices,
308 std::make_index_sequence<Plan::node_count> {});
309 static constexpr auto physical_slot_alignments =
311 physical_slot_indices,
312 std::make_index_sequence<Plan::node_count> {});
313 static constexpr auto physical_slot_policies =
315 physical_slot_indices,
316 std::make_index_sequence<Plan::node_count> {});
317
318 template <std::size_t I>
319 static constexpr std::size_t physical_slot_index = physical_slot_indices[I];
320
321 template <std::size_t K>
322 static constexpr slot_physical_policy physical_slot_policy = physical_slot_policies[K];
323};
324
332template <typename Layout, std::size_t... K>
333[[nodiscard]] auto make_erased_slots_tuple(std::index_sequence<K...>)
334 -> std::tuple<erased_slot<
335 Layout::physical_slot_sizes[K],
336 Layout::physical_slot_alignments[K],
337 Layout::template physical_slot_policy<K>>...>;
338
342template <typename Layout>
345 std::make_index_sequence<Layout::physical_slot_count> {}));
346
360template <typename Plan, std::size_t PhysicalSlot>
362 constexpr auto indices = make_one_to_one_physical_slot_indices<Plan>();
363 for (std::size_t node = 0; node < Plan::node_count; ++node) {
364 if (indices[node] == PhysicalSlot) {
365 return node;
366 }
367 }
368
369 return no_physical_slot;
370}
371
380template <typename Plan, std::size_t... K>
381[[nodiscard]] auto make_typed_slots_tuple(std::index_sequence<K...>)
382 -> std::tuple<typed_slot<
385
389template <typename Plan>
392 std::make_index_sequence<payload_node_count_v<Plan>> {}));
393
397template <typename Plan, std::size_t I>
400
401} // namespace yorch::detail
True when node I owns physical storage for its output.
Definition layout.hpp:398
constexpr std::size_t no_physical_slot
Sentinel physical slot index meaning "this node has no storage".
Definition policy.hpp:59
constexpr auto payload_node_array_v
Definition layout.hpp:46
consteval auto make_serial_dfs_compact_slot_layout()
Builds the serial-DFS compact node -> physical slot layout.
Definition layout.hpp:123
decltype(make_erased_slots_tuple< Layout >(std::make_index_sequence< Layout::physical_slot_count > {})) plan_erased_slots_tuple_t
Erased backend storage tuple for compact/layout-driven plan slots.
Definition layout.hpp:345
consteval auto make_one_to_one_physical_slot_indices()
Builds the one-to-one node -> physical slot index table.
Definition layout.hpp:72
consteval std::size_t one_to_one_physical_slot_owner_node()
Finds the unique node that owns a one-to-one physical slot.
Definition layout.hpp:361
auto make_erased_slots_tuple(std::index_sequence< K... >) -> std::tuple< erased_slot< Layout::physical_slot_sizes[K], Layout::physical_slot_alignments[K], Layout::template physical_slot_policy< K > >... >
Type factory for a layout's erased-slot storage tuple.
constexpr std::size_t payload_node_count_v
Definition layout.hpp:54
consteval auto make_payload_node_array(std::index_sequence< I... >)
Builds the compile-time node -> has-payload table for a plan.
Definition layout.hpp:24
consteval auto make_physical_slot_alignments(const std::array< std::size_t, Plan::node_count > &indices, std::index_sequence< I... >)
Computes the required alignment for each physical slot.
Definition layout.hpp:223
consteval auto make_physical_slot_policies(const std::array< std::size_t, Plan::node_count > &indices, std::index_sequence< I... >)
Computes the storage policy for each physical slot.
Definition layout.hpp:256
decltype(make_typed_slots_tuple< Plan >(std::make_index_sequence< payload_node_count_v< Plan > > {})) plan_typed_slots_tuple_t
Typed backend storage tuple for one-to-one owned payload slots.
Definition layout.hpp:392
constexpr slot_physical_policy join_slot_physical_policy(slot_physical_policy left, slot_logical_policy right) noexcept
Joins one node's logical policy into a physical slot policy.
Definition layout.hpp:156
constexpr auto slot_logical_policy_array_v
Definition layout.hpp:50
slot_physical_policy
Storage-level policy for a physical slot after layout selection.
Definition policy.hpp:32
consteval auto make_physical_slot_sizes(const std::array< std::size_t, Plan::node_count > &indices, std::index_sequence< I... >)
Computes the required raw storage size for each physical slot.
Definition layout.hpp:192
slot_logical_policy
Node-local slot semantics inferred from a task's result protocol.
Definition policy.hpp:17
auto make_typed_slots_tuple(std::index_sequence< K... >) -> std::tuple< typed_slot< typename Plan::template output_type< one_to_one_physical_slot_owner_node< Plan, K >()>, Plan::template slot_logical_policy_for< one_to_one_physical_slot_owner_node< Plan, K >()> >... >
Type factory for a plan's typed one-to-one slot tuple.
consteval auto make_slot_logical_policy_array(std::index_sequence< I... >)
Builds the compile-time node -> logical slot policy table.
Definition layout.hpp:39
constexpr bool is_adapter_descriptor_v
Definition adapters.hpp:63
Intermediate index data for the serial-DFS compact slot layout.
Definition layout.hpp:90
std::array< std::size_t, Plan::node_count > physical_slot_indices
Definition layout.hpp:92
std::array< std::size_t, Plan::node_count > payload_depths
Definition layout.hpp:94