openPMD-api
 
Loading...
Searching...
No Matches
ADIOS2PreloadAttributes.hpp
1/* Copyright 2020-2025 Franz Poeschel
2 *
3 * This file is part of openPMD-api.
4 *
5 * openPMD-api is free software: you can redistribute it and/or modify
6 * it under the terms of of either the GNU General Public License or
7 * the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * openPMD-api is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License and the GNU Lesser General Public License
15 * for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * and the GNU Lesser General Public License along with openPMD-api.
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21#pragma once
22
23#include "openPMD/config.hpp"
24#if openPMD_HAVE_ADIOS2
25
26#include <adios2.h>
27#include <map>
28#include <optional>
29#include <variant>
30
31#include "openPMD/Datatype.hpp"
32#include "openPMD/auxiliary/Variant.hpp"
33
34namespace openPMD::detail
35{
41template <typename T>
43{
44 size_t len;
45 T const *data;
46};
47
59class PreloadAdiosAttributes
60{
61public:
65 struct AttributeLocation
66 {
67 size_t len;
68 size_t offset;
69 Datatype dt;
70 char *destroy = nullptr;
71
72 AttributeLocation() = delete;
73 AttributeLocation(size_t len, size_t offset, Datatype dt);
74
75 AttributeLocation(AttributeLocation const &other) = delete;
76 AttributeLocation &operator=(AttributeLocation const &other) = delete;
77
78 AttributeLocation(AttributeLocation &&other) noexcept;
79 AttributeLocation &operator=(AttributeLocation &&other) noexcept;
80
81 ~AttributeLocation();
82 };
83
84private:
85 /*
86 * Allocate one large buffer instead of hundreds of single heap
87 * allocations.
88 * This will comply with alignment requirements, since
89 * std::allocator<char>::allocate() will call the untyped new operator
90 * ::operator new(std::size_t)
91 * https://en.cppreference.com/w/cpp/memory/allocator/allocate
92 */
93 std::vector<char> m_rawBuffer;
94 std::map<std::string, AttributeLocation> m_offsets;
95
96public:
97 explicit PreloadAdiosAttributes() = default;
98 PreloadAdiosAttributes(PreloadAdiosAttributes const &other) = delete;
99 PreloadAdiosAttributes &
100 operator=(PreloadAdiosAttributes const &other) = delete;
101
102 PreloadAdiosAttributes(PreloadAdiosAttributes &&other) = default;
103 PreloadAdiosAttributes &operator=(PreloadAdiosAttributes &&other) = default;
104
110 void preloadAttributes(adios2::IO &IO);
111
122 template <typename T>
123 AttributeWithShape<T> getAttribute(std::string const &name) const;
124
125 Datatype attributeType(std::string const &name) const;
126
127 std::map<std::string, AttributeLocation> const &availableAttributes() const;
128};
129
130template <typename T>
131struct AttributeWithShapeAndResource : AttributeWithShape<T>
132{
133 AttributeWithShapeAndResource(AttributeWithShape<T> parent);
134 AttributeWithShapeAndResource(
135 size_t len_in,
136 T const *data_in,
137 std::optional<std::vector<T>> resource_in);
138 AttributeWithShapeAndResource(adios2::Attribute<T> attr);
139 operator bool() const;
140
141private:
142 /*
143 * Users should still use the API of AttributeWithShape (parent type), we
144 * just need somewhere to store the std::vector<T> returned by
145 * Attribute<T>::Data(). This field will not be used when using preparsing,
146 * because the data pointer will go right into the preparse buffer.
147 */
148 std::optional<std::vector<T>> resource;
149};
150
152{
153 using RandomAccess_t = std::vector<PreloadAdiosAttributes>;
155 {
156 /*
157 * These are only buffered for performance reasons.
158 * IO::AvailableAttributes() returns by value, so we should avoid
159 * calling it too often. Instead, store the returned value along with
160 * the step, so we know when we need to update again (i.e. when the
161 * current step changes).
162 */
163 size_t m_currentStep = 0;
164 std::optional<std::map<std::string, adios2::Params>> m_attributes;
165 };
166
167 /*
168 * Variant RandomAcces_t has to be initialized explicitly by
169 * ADIOS2IOHandlerImpl::readAttributeAllsteps(), so we use StreamAccess_t by
170 * default.
171 */
172 std::variant<RandomAccess_t, StreamAccess_t> m_data = StreamAccess_t{};
173
174 /*
175 * Needs to be this somewhat ugly API since the AvailableAttributes map has
176 * a different type depending if we use preparsing or not. If we don't use
177 * preparsing, we just use the returned std::map<std::string,
178 * adios2::Params> from IO::AvailableAttributes(). Otherwise, we use the
179 * std::map<std::string, AttributeLocation> map from the
180 * PreloadAdiosAttributes class. The functor f will be called either with
181 * the one or the other, so needs to be written such that the mapped-to type
182 * does not matter.
183 */
184 template <typename Functor>
185 auto withAvailableAttributes(size_t step, adios2::IO &IO, Functor &&f)
186 -> decltype(std::forward<Functor>(f)(
187 std::declval<std::map<std::string, adios2::Params> &>()))
188 {
189 using ret_t = decltype(std::forward<Functor>(f)(
190 std::declval<std::map<std::string, adios2::Params> &>()));
191 return std::visit(
193 [step, &f](RandomAccess_t &ra) -> ret_t {
194 auto &attribute_data = ra.at(step);
195 return std::forward<Functor>(f)(
196 attribute_data.availableAttributes());
197 },
198 [step, &f, &IO](StreamAccess_t &sa) -> ret_t {
199 if (!sa.m_attributes.has_value() ||
200 sa.m_currentStep != step)
201 {
202 sa = StreamAccess_t{step, IO.AvailableAttributes()};
203 }
204 return std::forward<Functor>(f)(*sa.m_attributes);
205 }},
206 m_data);
207 }
208
209 template <typename T>
210 AttributeWithShapeAndResource<T>
211 getAttribute(size_t step, adios2::IO &IO, std::string const &name) const;
212};
213} // namespace openPMD::detail
214
215#endif // openPMD_HAVE_ADIOS2
void preloadAttributes(adios2::IO &IO)
Load attributes from the current step into the buffer.
Definition ADIOS2PreloadAttributes.cpp:177
AttributeWithShape< T > getAttribute(std::string const &name) const
Get an attribute that has been buffered previously.
Definition ADIOS2PreloadAttributes.cpp:241
@ T
time
Definition UnitDimension.hpp:41
Datatype
Concrete datatype of an object available at runtime.
Definition Datatype.hpp:51
Definition Variant.hpp:112
Definition ADIOS2PreloadAttributes.hpp:155
Definition ADIOS2PreloadAttributes.hpp:152
Pointer to an attribute's data along with its shape.
Definition ADIOS2PreloadAttributes.hpp:43