DDC 0.5.0
Loading...
Searching...
No Matches
chunk.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 <cassert>
8#include <string>
9#include <utility>
10
11#include <Kokkos_Core.hpp>
12
13#include "ddc/chunk_common.hpp"
14#include "ddc/chunk_span.hpp"
15#include "ddc/chunk_traits.hpp"
16#include "ddc/detail/kokkos.hpp"
17#include "ddc/kokkos_allocator.hpp"
18
19namespace ddc {
20
21template <class ElementType, class, class Allocator = HostAllocator<ElementType>>
22class Chunk;
23
24template <class ElementType, class SupportType, class Allocator>
25inline constexpr bool enable_chunk<Chunk<ElementType, SupportType, Allocator>> = true;
26
27template <class ElementType, class... DDims, class Allocator>
28class Chunk<ElementType, DiscreteDomain<DDims...>, Allocator>
29 : public ChunkCommon<ElementType, DiscreteDomain<DDims...>, Kokkos::layout_right>
30{
31protected:
32 using base_type = ChunkCommon<ElementType, DiscreteDomain<DDims...>, Kokkos::layout_right>;
33
34 /// ND memory view
35 using internal_mdspan_type = typename base_type::internal_mdspan_type;
36
37public:
38 /// type of a span of this full chunk
39 using span_type = ChunkSpan<
40 ElementType,
41 DiscreteDomain<DDims...>,
42 Kokkos::layout_right,
43 typename Allocator::memory_space>;
44
45 /// type of a view of this full chunk
46 using view_type = ChunkSpan<
47 ElementType const,
48 DiscreteDomain<DDims...>,
49 Kokkos::layout_right,
50 typename Allocator::memory_space>;
51
52 /// The dereferenceable part of the co-domain but with indexing starting at 0
53 using allocation_mdspan_type = typename base_type::allocation_mdspan_type;
54
55 using const_allocation_mdspan_type = typename base_type::const_allocation_mdspan_type;
56
57 using discrete_domain_type = typename base_type::discrete_domain_type;
58
59 using memory_space = typename Allocator::memory_space;
60
61 using discrete_element_type = typename base_type::discrete_element_type;
62
63 using extents_type = typename base_type::extents_type;
64
65 using layout_type = typename base_type::layout_type;
66
67 using mapping_type = typename base_type::mapping_type;
68
69 using element_type = typename base_type::element_type;
70
71 using value_type = typename base_type::value_type;
72
73 using size_type = typename base_type::size_type;
74
75 using data_handle_type = typename base_type::data_handle_type;
76
77 using reference = typename base_type::reference;
78
79 template <class, class, class>
80 friend class Chunk;
81
82private:
83 Allocator m_allocator;
84
85 std::string m_label;
86
87public:
88 /// Empty Chunk
89 Chunk() = default;
90
91 /// Construct a labeled Chunk on a domain with uninitialized values
92 explicit Chunk(
93 std::string const& label,
94 discrete_domain_type const& domain,
95 Allocator allocator = Allocator())
96 : base_type(allocator.allocate(label, domain.size()), domain)
97 , m_allocator(std::move(allocator))
98 , m_label(label)
99 {
100 }
101
102 /// Construct a Chunk on a domain with uninitialized values
103 explicit Chunk(discrete_domain_type const& domain, Allocator allocator = Allocator())
104 : Chunk("no-label", domain, std::move(allocator))
105 {
106 }
107
108 /// Deleted: use deepcopy instead
109 Chunk(Chunk const& other) = delete;
110
111 /** Constructs a new Chunk by move
112 * @param other the Chunk to move
113 */
114 Chunk(Chunk&& other) noexcept
115 : base_type(std::move(static_cast<base_type&>(other)))
116 , m_allocator(std::move(other.m_allocator))
117 , m_label(std::move(other.m_label))
118 {
119 other.m_internal_mdspan = internal_mdspan_type(nullptr, other.m_internal_mdspan.mapping());
120 }
121
122 ~Chunk() noexcept
123 {
124 if (this->m_internal_mdspan.data_handle()) {
125 m_allocator.deallocate(this->data_handle(), this->size());
126 }
127 }
128
129 /// Deleted: use deepcopy instead
130 Chunk& operator=(Chunk const& other) = delete;
131
132 /** Move-assigns a new value to this field
133 * @param other the Chunk to move
134 * @return *this
135 */
136 Chunk& operator=(Chunk&& other) noexcept
137 {
138 if (this == &other) {
139 return *this;
140 }
141 if (this->m_internal_mdspan.data_handle()) {
142 m_allocator.deallocate(this->data_handle(), this->size());
143 }
144 static_cast<base_type&>(*this) = std::move(static_cast<base_type&>(other));
145 m_allocator = std::move(other.m_allocator);
146 m_label = std::move(other.m_label);
147 other.m_internal_mdspan = internal_mdspan_type(nullptr, other.m_internal_mdspan.mapping());
148
149 return *this;
150 }
151
152 /// Slice out some dimensions
153 template <class... QueryDDims>
154 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec) const
155 {
156 return view_type(*this)[slice_spec];
157 }
158
159 /// Slice out some dimensions
160 template <class... QueryDDims>
161 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec)
162 {
163 return span_view()[slice_spec];
164 }
165
166 /// Slice out some dimensions
167 template <class... QueryDDims>
168 auto operator[](DiscreteDomain<QueryDDims...> const& odomain) const
169 {
170 return span_view()[odomain];
171 }
172
173 /// Slice out some dimensions
174 template <class... QueryDDims>
175 auto operator[](DiscreteDomain<QueryDDims...> const& odomain)
176 {
177 return span_view()[odomain];
178 }
179
180 /** Element access using a list of DiscreteElement
181 * @param delems discrete coordinates
182 * @return const-reference to this element
183 */
184 template <class... DElems>
185 element_type const& operator()(DElems const&... delems) const noexcept
186 {
187 static_assert(
188 sizeof...(DDims) == (0 + ... + DElems::size()),
189 "Invalid number of dimensions");
190 static_assert((is_discrete_element_v<DElems> && ...), "Expected DiscreteElements");
191 assert(((DiscreteElement<DDims>(take<DDims>(delems...)) >= front<DDims>(this->m_domain))
192 && ...));
193 assert(((DiscreteElement<DDims>(take<DDims>(delems...)) <= back<DDims>(this->m_domain))
194 && ...));
195 return DDC_MDSPAN_ACCESS_OP(this->m_internal_mdspan, uid<DDims>(take<DDims>(delems...))...);
196 }
197
198 /** Element access using a list of DiscreteElement
199 * @param delems discrete coordinates
200 * @return reference to this element
201 */
202 template <class... DElems>
203 element_type& operator()(DElems const&... delems) noexcept
204 {
205 static_assert(
206 sizeof...(DDims) == (0 + ... + DElems::size()),
207 "Invalid number of dimensions");
208 static_assert((is_discrete_element_v<DElems> && ...), "Expected DiscreteElements");
209 assert(((DiscreteElement<DDims>(take<DDims>(delems...)) >= front<DDims>(this->m_domain))
210 && ...));
211 assert(((DiscreteElement<DDims>(take<DDims>(delems...)) <= back<DDims>(this->m_domain))
212 && ...));
213 return DDC_MDSPAN_ACCESS_OP(this->m_internal_mdspan, uid<DDims>(take<DDims>(delems...))...);
214 }
215
216 /** Returns the label of the Chunk
217 * @return c-string
218 */
219 char const* label() const
220 {
221 return m_label.c_str();
222 }
223
224 /** Access to the underlying allocation pointer
225 * @return read-only allocation pointer
226 */
227 ElementType const* data_handle() const
228 {
229 return base_type::data_handle();
230 }
231
232 /** Access to the underlying allocation pointer
233 * @return allocation pointer
234 */
235 ElementType* data_handle()
236 {
237 return base_type::data_handle();
238 }
239
240 /** Provide a mdspan on the memory allocation
241 * @return read-only allocation mdspan
242 */
243 const_allocation_mdspan_type allocation_mdspan() const
244 {
245 return base_type::allocation_mdspan();
246 }
247
248 /** Provide a mdspan on the memory allocation
249 * @return allocation mdspan
250 */
251 allocation_mdspan_type allocation_mdspan()
252 {
253 return base_type::allocation_mdspan();
254 }
255
256 /** Provide an unmanaged `Kokkos::View` on the memory allocation
257 * @return allocation `Kokkos::View`
258 */
260 {
261 auto s = this->allocation_mdspan();
262 auto kokkos_layout = detail::build_kokkos_layout(
263 s.extents(),
264 s.mapping(),
265 std::make_index_sequence<sizeof...(DDims)> {});
266 return Kokkos::View<
267 detail::mdspan_to_kokkos_element_t<ElementType, sizeof...(DDims)>,
268 decltype(kokkos_layout),
269 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
270 }
271
272 /** Provide an unmanaged `Kokkos::View` on the memory allocation
273 * @return read-only allocation `Kokkos::View`
274 */
275 auto allocation_kokkos_view() const
276 {
277 auto s = this->allocation_mdspan();
278 auto kokkos_layout = detail::build_kokkos_layout(
279 s.extents(),
280 s.mapping(),
281 std::make_index_sequence<sizeof...(DDims)> {});
282 return Kokkos::View<
283 detail::mdspan_to_kokkos_element_t<const ElementType, sizeof...(DDims)>,
284 decltype(kokkos_layout),
285 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
286 }
287
288 view_type span_cview() const
289 {
290 return view_type(*this);
291 }
292
293 view_type span_view() const
294 {
295 return view_type(*this);
296 }
297
298 span_type span_view()
299 {
300 return span_type(*this);
301 }
302};
303
304template <class ElementType, class SupportType, class Allocator>
305class Chunk : public ChunkCommon<ElementType, SupportType, Kokkos::layout_right>
306{
307protected:
308 using base_type = ChunkCommon<ElementType, SupportType, Kokkos::layout_right>;
309
310public:
311 /// type of a span of this full chunk
312 using span_type = ChunkSpan<
313 ElementType,
314 SupportType,
315 Kokkos::layout_right,
316 typename Allocator::memory_space>;
317
318 /// type of a view of this full chunk
319 using view_type = ChunkSpan<
320 ElementType const,
321 SupportType,
322 Kokkos::layout_right,
323 typename Allocator::memory_space>;
324
325 /// The dereferenceable part of the co-domain but with indexing starting at 0
326 using allocation_mdspan_type = typename base_type::allocation_mdspan_type;
327
328 using const_allocation_mdspan_type = typename base_type::const_allocation_mdspan_type;
329
330 using discrete_domain_type = typename base_type::discrete_domain_type;
331
332 using memory_space = typename Allocator::memory_space;
333
334 using discrete_element_type = typename base_type::discrete_element_type;
335
336 using extents_type = typename base_type::extents_type;
337
338 using layout_type = typename base_type::layout_type;
339
340 using mapping_type = typename base_type::mapping_type;
341
342 using element_type = typename base_type::element_type;
343
344 using value_type = typename base_type::value_type;
345
346 using size_type = typename base_type::size_type;
347
348 using data_handle_type = typename base_type::data_handle_type;
349
350 using reference = typename base_type::reference;
351
352 template <class, class, class>
353 friend class Chunk;
354
355private:
356 Allocator m_allocator;
357
358 std::string m_label;
359
360public:
361 /// Empty Chunk
362 Chunk() = default;
363
364 /// Construct a labeled Chunk on a domain with uninitialized values
365 explicit Chunk(
366 std::string const& label,
367 SupportType const& domain,
368 Allocator allocator = Allocator())
369 : base_type(allocator.allocate(label, domain.size()), domain)
370 , m_allocator(std::move(allocator))
371 , m_label(label)
372 {
373 }
374
375 /// Construct a Chunk on a domain with uninitialized values
376 explicit Chunk(SupportType const& domain, Allocator allocator = Allocator())
377 : Chunk("no-label", domain, std::move(allocator))
378 {
379 }
380
381 /// Deleted: use deepcopy instead
382 Chunk(Chunk const& other) = delete;
383
384 /** Constructs a new Chunk by move
385 * @param other the Chunk to move
386 */
387 Chunk(Chunk&& other) noexcept
388 : base_type(std::move(static_cast<base_type&>(other)))
389 , m_allocator(std::move(other.m_allocator))
390 , m_label(std::move(other.m_label))
391 {
392 other.m_allocation_mdspan
393 = allocation_mdspan_type(nullptr, other.m_allocation_mdspan.mapping());
394 }
395
396 ~Chunk() noexcept
397 {
398 if (this->m_allocation_mdspan.data_handle()) {
399 m_allocator.deallocate(this->data_handle(), this->size());
400 }
401 }
402
403 /// Deleted: use deepcopy instead
404 Chunk& operator=(Chunk const& other) = delete;
405
406 /** Move-assigns a new value to this field
407 * @param other the Chunk to move
408 * @return *this
409 */
410 Chunk& operator=(Chunk&& other) noexcept
411 {
412 if (this == &other) {
413 return *this;
414 }
415 if (this->m_allocation_mdspan.data_handle()) {
416 m_allocator.deallocate(this->data_handle(), this->size());
417 }
418 static_cast<base_type&>(*this) = std::move(static_cast<base_type&>(other));
419 m_allocator = std::move(other.m_allocator);
420 m_label = std::move(other.m_label);
421 other.m_allocation_mdspan
422 = allocation_mdspan_type(nullptr, other.m_allocation_mdspan.mapping());
423
424 return *this;
425 }
426
427 /// Slice out some dimensions
428 template <class... QueryDDims>
429 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec) const
430 {
431 return view_type(*this)[slice_spec];
432 }
433
434 /// Slice out some dimensions
435 template <class... QueryDDims>
436 auto operator[](DiscreteElement<QueryDDims...> const& slice_spec)
437 {
438 return span_view()[slice_spec];
439 }
440
441 /** Element access using a list of DiscreteElement
442 * @param delems discrete coordinates
443 * @return const-reference to this element
444 */
445 template <class... DElems>
446 element_type const& operator()(DElems const&... delems) const noexcept
447 {
448 static_assert(
449 SupportType::rank() == (0 + ... + DElems::size()),
450 "Invalid number of dimensions");
451 static_assert((is_discrete_element_v<DElems> && ...), "Expected DiscreteElements");
452 assert(this->m_domain.contains(delems...));
453 return DDC_MDSPAN_ACCESS_OP(
454 this->m_allocation_mdspan,
455 detail::array(this->m_domain.distance_from_front(delems...)));
456 }
457
458 /** Element access using a list of DiscreteElement
459 * @param delems discrete coordinates
460 * @return reference to this element
461 */
462 template <class... DElems>
463 element_type& operator()(DElems const&... delems) noexcept
464 {
465 static_assert(
466 SupportType::rank() == (0 + ... + DElems::size()),
467 "Invalid number of dimensions");
468 static_assert((is_discrete_element_v<DElems> && ...), "Expected DiscreteElements");
469 assert(this->m_domain.contains(delems...));
470 return DDC_MDSPAN_ACCESS_OP(
471 this->m_allocation_mdspan,
472 detail::array(this->m_domain.distance_from_front(delems...)));
473 }
474
475 /** Returns the label of the Chunk
476 * @return c-string
477 */
478 char const* label() const
479 {
480 return m_label.c_str();
481 }
482
483 /** Access to the underlying allocation pointer
484 * @return read-only allocation pointer
485 */
486 ElementType const* data_handle() const
487 {
488 return base_type::data_handle();
489 }
490
491 /** Access to the underlying allocation pointer
492 * @return allocation pointer
493 */
494 ElementType* data_handle()
495 {
496 return base_type::data_handle();
497 }
498
499 /** Provide a mdspan on the memory allocation
500 * @return read-only allocation mdspan
501 */
502 const_allocation_mdspan_type allocation_mdspan() const
503 {
504 return base_type::allocation_mdspan();
505 }
506
507 /** Provide a mdspan on the memory allocation
508 * @return allocation mdspan
509 */
510 allocation_mdspan_type allocation_mdspan()
511 {
512 return base_type::allocation_mdspan();
513 }
514
515 /** Provide an unmanaged `Kokkos::View` on the memory allocation
516 * @return allocation `Kokkos::View`
517 */
519 {
520 auto s = this->allocation_mdspan();
521 auto kokkos_layout = detail::build_kokkos_layout(
522 s.extents(),
523 s.mapping(),
524 std::make_index_sequence<SupportType::rank()> {});
525 return Kokkos::View<
526 detail::mdspan_to_kokkos_element_t<ElementType, SupportType::rank()>,
527 decltype(kokkos_layout),
528 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
529 }
530
531 /** Provide an unmanaged `Kokkos::View` on the memory allocation
532 * @return read-only allocation `Kokkos::View`
533 */
534 auto allocation_kokkos_view() const
535 {
536 auto s = this->allocation_mdspan();
537 auto kokkos_layout = detail::build_kokkos_layout(
538 s.extents(),
539 s.mapping(),
540 std::make_index_sequence<SupportType::rank()> {});
541 return Kokkos::View<
542 detail::mdspan_to_kokkos_element_t<const ElementType, SupportType::rank()>,
543 decltype(kokkos_layout),
544 typename Allocator::memory_space>(s.data_handle(), kokkos_layout);
545 }
546
547 view_type span_cview() const
548 {
549 return view_type(*this);
550 }
551
552 view_type span_view() const
553 {
554 return view_type(*this);
555 }
556
557 span_type span_view()
558 {
559 return span_type(*this);
560 }
561};
562
563template <class SupportType, class Allocator>
564Chunk(std::string const&,
565 SupportType const&,
566 Allocator) -> Chunk<typename Allocator::value_type, SupportType, Allocator>;
567
568template <class SupportType, class Allocator>
569Chunk(SupportType const&,
570 Allocator) -> Chunk<typename Allocator::value_type, SupportType, Allocator>;
571
572} // namespace ddc
auto operator[](DiscreteDomain< QueryDDims... > const &odomain)
Slice out some dimensions.
Definition chunk.hpp:175
auto operator[](DiscreteDomain< QueryDDims... > const &odomain) const
Slice out some dimensions.
Definition chunk.hpp:168
Chunk(discrete_domain_type const &domain, Allocator allocator=Allocator())
Construct a Chunk on a domain with uninitialized values.
Definition chunk.hpp:103
Chunk(Chunk &&other) noexcept
Constructs a new Chunk by move.
Definition chunk.hpp:114
element_type const & operator()(DElems const &... delems) const noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:185
allocation_mdspan_type allocation_mdspan()
Provide a mdspan on the memory allocation.
Definition chunk.hpp:251
ElementType * data_handle()
Access to the underlying allocation pointer.
Definition chunk.hpp:235
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec) const
Slice out some dimensions.
Definition chunk.hpp:154
Chunk & operator=(Chunk const &other)=delete
Deleted: use deepcopy instead.
const_allocation_mdspan_type allocation_mdspan() const
Provide a mdspan on the memory allocation.
Definition chunk.hpp:243
Chunk & operator=(Chunk &&other) noexcept
Move-assigns a new value to this field.
Definition chunk.hpp:136
auto allocation_kokkos_view() const
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:275
ElementType const * data_handle() const
Access to the underlying allocation pointer.
Definition chunk.hpp:227
auto allocation_kokkos_view()
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:259
Chunk(Chunk const &other)=delete
Deleted: use deepcopy instead.
Chunk(std::string const &label, discrete_domain_type const &domain, Allocator allocator=Allocator())
Construct a labeled Chunk on a domain with uninitialized values.
Definition chunk.hpp:92
char const * label() const
Returns the label of the Chunk.
Definition chunk.hpp:219
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec)
Slice out some dimensions.
Definition chunk.hpp:161
element_type & operator()(DElems const &... delems) noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:203
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec) const
Slice out some dimensions.
Definition chunk.hpp:429
char const * label() const
Returns the label of the Chunk.
Definition chunk.hpp:478
const_allocation_mdspan_type allocation_mdspan() const
Provide a mdspan on the memory allocation.
Definition chunk.hpp:502
ElementType const * data_handle() const
Access to the underlying allocation pointer.
Definition chunk.hpp:486
auto allocation_kokkos_view()
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:518
auto allocation_kokkos_view() const
Provide an unmanaged Kokkos::View on the memory allocation.
Definition chunk.hpp:534
Chunk(SupportType const &domain, Allocator allocator=Allocator())
Construct a Chunk on a domain with uninitialized values.
Definition chunk.hpp:376
Chunk & operator=(Chunk const &other)=delete
Deleted: use deepcopy instead.
allocation_mdspan_type allocation_mdspan()
Provide a mdspan on the memory allocation.
Definition chunk.hpp:510
ElementType * data_handle()
Access to the underlying allocation pointer.
Definition chunk.hpp:494
view_type span_cview() const
Definition chunk.hpp:547
Chunk(Chunk const &other)=delete
Deleted: use deepcopy instead.
~Chunk() noexcept
Definition chunk.hpp:396
Chunk(std::string const &label, SupportType const &domain, Allocator allocator=Allocator())
Construct a labeled Chunk on a domain with uninitialized values.
Definition chunk.hpp:365
element_type & operator()(DElems const &... delems) noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:463
Chunk()=default
Empty Chunk.
Chunk & operator=(Chunk &&other) noexcept
Move-assigns a new value to this field.
Definition chunk.hpp:410
Chunk(Chunk &&other) noexcept
Constructs a new Chunk by move.
Definition chunk.hpp:387
span_type span_view()
Definition chunk.hpp:557
view_type span_view() const
Definition chunk.hpp:552
element_type const & operator()(DElems const &... delems) const noexcept
Element access using a list of DiscreteElement.
Definition chunk.hpp:446
auto operator[](DiscreteElement< QueryDDims... > const &slice_spec)
Slice out some dimensions.
Definition chunk.hpp:436
friend class DiscreteDomain
The top-level namespace of DDC.
constexpr bool enable_chunk< Chunk< ElementType, SupportType, Allocator > >
Definition chunk.hpp:25
Chunk(SupportType const &, Allocator) -> Chunk< typename Allocator::value_type, SupportType, Allocator >
Chunk(std::string const &, SupportType const &, Allocator) -> Chunk< typename Allocator::value_type, SupportType, Allocator >