DDC 0.0.0

a discrete domain computation library

pdi.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <memory_resource>
8#include <string>
9#include <type_traits>
10#include <utility>
11#include <vector>
12
13#include <pdi.h>
14
15#include "ddc/chunk_traits.hpp"
16
17#include "chunk_span.hpp"
18
19namespace ddc {
20
21template <class T>
22static constexpr PDI_inout_t default_access_v
23 = (std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>>)
24 ? PDI_INOUT
25 : PDI_OUT;
26
27template <class T>
28static constexpr PDI_inout_t chunk_default_access_v = is_writable_chunk_v<T> ? PDI_INOUT : PDI_OUT;
29
30class PdiEvent
31{
32 std::string m_event_name;
33
34 std::vector<std::string> m_names;
35
36 /// a memory buffer where temporary variables are stored until the class is destroyed
37 std::pmr::monotonic_buffer_resource m_metadata;
38
39public:
40 explicit PdiEvent(std::string const& event_name) : m_event_name(event_name) {}
41
42 PdiEvent(PdiEvent const& rhs) = delete;
43
44 PdiEvent(PdiEvent&& rhs) noexcept = delete;
45
46 ~PdiEvent() noexcept
47 {
48 PDI_event(m_event_name.c_str());
49 for (std::string const& one_name : m_names) {
50 PDI_reclaim(one_name.c_str());
51 }
52 }
53
54 PdiEvent& operator=(PdiEvent const& rhs) = delete;
55
56 PdiEvent& operator=(PdiEvent&& rhs) noexcept = delete;
57
58 /// @{
59 /// API with access argument
60
61 template <
62 PDI_inout_t access,
63 class BorrowedChunk,
64 std::enable_if_t<is_borrowed_chunk_v<BorrowedChunk>, int> = 0>
65 PdiEvent& with(std::string const& name, BorrowedChunk&& data)
66 {
67 static_assert(
68 !(access & PDI_IN) || (chunk_default_access_v<BorrowedChunk> & PDI_IN),
69 "Invalid access for constant data");
70 auto extents = detail::array(data.domain().extents());
71 std::size_t& rank = *std::pmr::polymorphic_allocator<std::size_t>(&m_metadata).allocate(1);
72 rank = extents.size();
73 PDI_share((name + "_rank").c_str(), &rank, PDI_OUT);
74 m_names.push_back(name + "_rank");
75 PDI_share(
76 (name + "_extents").c_str(),
77 std::pmr::vector<std::size_t>(extents.begin(), extents.end(), &m_metadata).data(),
78 PDI_OUT);
79 m_names.push_back(name + "_extents");
80 PDI_share(
81 name.c_str(),
82 const_cast<chunk_value_t<BorrowedChunk>*>(data.data_handle()),
83 access);
84 m_names.push_back(name);
85 return *this;
86 }
87
88 template <
89 PDI_inout_t access,
90 class Arithmetic,
91 std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<Arithmetic>>, int> = 0>
92 PdiEvent& with(std::string const& name, Arithmetic&& data)
93 {
94 static_assert(
95 !(access & PDI_IN) || (default_access_v<Arithmetic> & PDI_IN),
96 "Invalid access for constant data");
97 using value_type = std::remove_cv_t<std::remove_reference_t<Arithmetic>>;
98 value_type* data_ptr = const_cast<value_type*>(&data);
99 // for read-only data, we share a copy instead of the data itself in case we received a ref on a temporary,
100 if constexpr (!(access & PDI_IN)) {
101 data_ptr = std::pmr::polymorphic_allocator<value_type>(&m_metadata).allocate(1);
102 *data_ptr = data;
103 }
104 PDI_share(name.c_str(), data_ptr, access);
105 m_names.push_back(name);
106 return *this;
107 }
108
109 template <PDI_inout_t access, class T>
110 PdiEvent& and_with(std::string const& name, T&& t)
111 {
112 return with<access>(name, std::forward<T>(t));
113 }
114
115 /// @}
116 /// API with access deduction
117 /// @{
118
119 /// Borrowed chunk overload (Chunk (const)& or ChunkSpan&& or ChunkSpan (const)&)
120 template <class BorrowedChunk, std::enable_if_t<is_borrowed_chunk_v<BorrowedChunk>, int> = 0>
121 PdiEvent& with(std::string const& name, BorrowedChunk&& data)
122 {
123 return with<chunk_default_access_v<BorrowedChunk>>(name, std::forward<BorrowedChunk>(data));
124 }
125
126 /// Arithmetic overload
127 template <
128 class Arithmetic,
129 std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<Arithmetic>>, int> = 0>
130 PdiEvent& with(std::string const& name, Arithmetic&& data)
131 {
132 return with<default_access_v<Arithmetic>>(name, std::forward<Arithmetic>(data));
133 }
134
135 /// With synonym
136 template <class T>
137 PdiEvent& and_with(std::string const& name, T&& t)
138 {
139 return with(name, std::forward<T>(t));
140 }
141
142 /// @}
143};
144
145template <PDI_inout_t access, class DataType>
146void expose_to_pdi(std::string const& name, DataType&& data)
147{
148 PdiEvent(name).with<access>(name, std::forward<DataType>(data));
149}
150
151template <class DataType>
152void expose_to_pdi(std::string const& name, DataType&& data)
153{
154 PdiEvent(name).with(name, std::forward<DataType>(data));
155}
156
157} // namespace ddc
Definition pdi.hpp:31
PdiEvent(PdiEvent const &rhs)=delete
PdiEvent & and_with(std::string const &name, T &&t)
With synonym.
Definition pdi.hpp:137
PdiEvent & and_with(std::string const &name, T &&t)
Definition pdi.hpp:110
PdiEvent & operator=(PdiEvent &&rhs) noexcept=delete
~PdiEvent() noexcept
Definition pdi.hpp:46
PdiEvent & operator=(PdiEvent const &rhs)=delete
PdiEvent(std::string const &event_name)
Definition pdi.hpp:40
PdiEvent & with(std::string const &name, Arithmetic &&data)
Arithmetic overload.
Definition pdi.hpp:130
PdiEvent & with(std::string const &name, BorrowedChunk &&data)
API with access deduction.
Definition pdi.hpp:121
PdiEvent & with(std::string const &name, Arithmetic &&data)
Definition pdi.hpp:92
PdiEvent & with(std::string const &name, BorrowedChunk &&data)
Definition pdi.hpp:65
PdiEvent(PdiEvent &&rhs) noexcept=delete
The top-level namespace of DDC.
Definition aligned_allocator.hpp:11
void expose_to_pdi(std::string const &name, DataType &&data)
Definition pdi.hpp:146
void expose_to_pdi(std::string const &name, DataType &&data)
Definition pdi.hpp:152