stdgpu/memory.h Source File

stdgpu/memory.h Source File#

stdgpu: stdgpu/memory.h Source File
stdgpu Latest
Efficient STL-like Data Structures on the GPU
memory.h
Go to the documentation of this file.
1/*
2 * Copyright 2019 Patrick Stotko
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef STDGPU_MEMORY_H
17#define STDGPU_MEMORY_H
18
28#include <cstdint>
29#include <functional>
30#include <memory>
31#include <type_traits>
32
33#include <stdgpu/config.h>
34#include <stdgpu/cstddef.h>
35#include <stdgpu/execution.h>
36#include <stdgpu/platform.h>
37#include <stdgpu/type_traits.h>
38
48template <typename T>
49[[nodiscard]] T*
50createDeviceArray(const stdgpu::index64_t count, const T default_value = T());
51
61template <typename T>
62[[nodiscard]] T*
63createHostArray(const stdgpu::index64_t count, const T default_value = T());
64
71template <typename T>
72void
73destroyDeviceArray(T*& device_array);
74
81template <typename T>
82void
83destroyHostArray(T*& host_array);
84
89enum class MemoryCopy : std::int8_t
90{
91 NO_CHECK,
94};
95
105template <typename T>
106[[nodiscard]] T*
107copyCreateDevice2HostArray(const T* device_array,
108 const stdgpu::index64_t count,
109 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
110
120template <typename T>
121[[nodiscard]] T*
122copyCreateHost2DeviceArray(const T* host_array,
123 const stdgpu::index64_t count,
124 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
125
135template <typename T>
136[[nodiscard]] T*
137copyCreateHost2HostArray(const T* host_array,
138 const stdgpu::index64_t count,
139 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
140
150template <typename T>
151[[nodiscard]] T*
152copyCreateDevice2DeviceArray(const T* device_array,
153 const stdgpu::index64_t count,
154 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
155
165template <typename T>
166void
167copyDevice2HostArray(const T* source_device_array,
168 const stdgpu::index64_t count,
169 T* destination_host_array,
170 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
171
181template <typename T>
182void
183copyHost2DeviceArray(const T* source_host_array,
184 const stdgpu::index64_t count,
185 T* destination_device_array,
186 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
187
197template <typename T>
198void
199copyHost2HostArray(const T* source_host_array,
200 const stdgpu::index64_t count,
201 T* destination_host_array,
202 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
203
213template <typename T>
214void
215copyDevice2DeviceArray(const T* source_device_array,
216 const stdgpu::index64_t count,
217 T* destination_device_array,
218 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
219
220namespace stdgpu
221{
222
228{
230 constexpr explicit null_object_t(int /* unspecified */) { }
232};
233
238inline constexpr null_object_t null_object{ 0 };
239
245template <typename T>
247{
248public:
252 explicit device_unique_object(null_object_t /*null_object*/);
253
259 template <typename... Args>
260 explicit device_unique_object(Args&&... args);
261
269 template <typename ExecutionPolicy,
270 typename... Args,
271 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
272 explicit device_unique_object(ExecutionPolicy&& policy, Args&&... args);
273
278 const T*
279 operator->() const;
280
285 T*
287
292 const T&
293 operator*() const;
294
299 T&
301
306 explicit
307 operator bool() const;
308
309private:
310 std::unique_ptr<T, std::function<void(T*)>> _object;
311};
312
317enum class dynamic_memory_type : std::int8_t
318{
319 host,
320 device,
321 invalid
322};
323
330template <typename T>
333
339template <typename T>
341{
342 using value_type = T;
348
352 safe_device_allocator() noexcept = default;
353
357 ~safe_device_allocator() noexcept = default;
358
363
369 template <typename U>
370 explicit safe_device_allocator(const safe_device_allocator<U>& other) noexcept;
371
377 operator=(const safe_device_allocator&) noexcept = default;
378
383
389 operator=(safe_device_allocator&&) noexcept = default;
390
396 [[nodiscard]] T*
398
404 void
406};
407
413template <typename T>
415{
416 using value_type = T;
422
426 safe_host_allocator() noexcept = default;
427
431 ~safe_host_allocator() noexcept = default;
432
436 safe_host_allocator(const safe_host_allocator&) noexcept = default;
437
443 template <typename U>
444 explicit safe_host_allocator(const safe_host_allocator<U>& other) noexcept;
445
451 operator=(const safe_host_allocator&) noexcept = default;
452
457
463 operator=(safe_host_allocator&&) noexcept = default;
464
470 [[nodiscard]] T*
472
478 void
480};
481
490template <typename Allocator>
492{
493 using allocator_type = Allocator;
494 using value_type = typename Allocator::value_type;
496 using const_pointer = typename std::pointer_traits<pointer>::template rebind<
497 const value_type>;
498 using void_pointer = typename std::pointer_traits<pointer>::template rebind<
499 void>;
500 using const_void_pointer = typename std::pointer_traits<pointer>::template rebind<
501 const void>;
503 typename std::pointer_traits<pointer>::difference_type;
508 using propagate_on_container_swap = std::false_type;
509 using is_always_equal = std::is_empty<Allocator>;
510 template <typename T>
511 using rebind_alloc = typename std::allocator_traits<Allocator>::template rebind_alloc<
512 T>;
513 template <typename T>
522 [[nodiscard]] static pointer
523 allocate(Allocator& a, index_type n);
524
532 [[nodiscard]] static pointer
533 allocate(Allocator& a, index_type n, const_void_pointer hint);
534
541 static void
542 deallocate(Allocator& a, pointer p, index_type n);
543
553 template <typename ExecutionPolicy,
554 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
555 [[nodiscard]] static pointer
556 allocate_filled(ExecutionPolicy&& policy, Allocator& a, index_type n, const value_type& default_value);
557
566 template <typename ExecutionPolicy,
567 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
568 static void
569 deallocate_filled(ExecutionPolicy&& policy, Allocator& a, pointer p, index_type n);
570
579 template <typename T, class... Args>
580 static STDGPU_HOST_DEVICE void
581 construct(Allocator& a, T* p, Args&&... args);
582
589 template <typename T>
590 static STDGPU_HOST_DEVICE void
591 destroy(Allocator& a, T* p);
592
599 max_size(const Allocator& a) noexcept;
600
606 static Allocator
608};
609
617template <typename T>
619to_address(T* p) noexcept;
620
628template <typename Ptr>
630to_address(const Ptr& p) noexcept;
631
641template <typename T, typename... Args>
643construct_at(T* p, Args&&... args);
644
651template <typename T>
654
655#ifdef STDGPU_RUN_DOXYGEN
656
668template <typename ExecutionPolicy,
669 typename Iterator,
670 typename T,
671 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
672void
673uninitialized_fill(ExecutionPolicy&& policy, Iterator begin, Iterator end, const T& value);
674
688template <typename ExecutionPolicy,
689 typename Iterator,
690 typename Size,
691 typename T,
692 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
693Iterator
694uninitialized_fill_n(ExecutionPolicy&& policy, Iterator begin, Size n, const T& value);
695
708template <typename ExecutionPolicy,
709 typename InputIt,
710 typename OutputIt,
711 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
712OutputIt
713uninitialized_copy(ExecutionPolicy&& policy, InputIt begin, InputIt end, OutputIt output_begin);
714
728template <typename ExecutionPolicy,
729 typename InputIt,
730 typename Size,
731 typename OutputIt,
732 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
733OutputIt
734uninitialized_copy_n(ExecutionPolicy&& policy, InputIt begin, Size n, OutputIt output_begin);
735
745template <typename ExecutionPolicy,
746 typename Iterator,
747 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
748void
749destroy(ExecutionPolicy&& policy, Iterator first, Iterator last);
750
762template <typename ExecutionPolicy,
763 typename Iterator,
764 typename Size,
765 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
766Iterator
767destroy_n(ExecutionPolicy&& policy, Iterator first, Size n);
768
769#endif
770
772namespace adl_barrier
773{
774
775template <typename ExecutionPolicy,
776 typename Iterator,
777 typename T,
778 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
779void
780uninitialized_fill(ExecutionPolicy&& policy, Iterator begin, Iterator end, const T& value);
781
782template <typename ExecutionPolicy,
783 typename Iterator,
784 typename Size,
785 typename T,
786 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
787Iterator
788uninitialized_fill_n(ExecutionPolicy&& policy, Iterator begin, Size n, const T& value);
789
790template <typename ExecutionPolicy,
791 typename InputIt,
792 typename OutputIt,
793 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
794OutputIt
795uninitialized_copy(ExecutionPolicy&& policy, InputIt begin, InputIt end, OutputIt output_begin);
796
797template <typename ExecutionPolicy,
798 typename InputIt,
799 typename Size,
800 typename OutputIt,
801 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
802OutputIt
803uninitialized_copy_n(ExecutionPolicy&& policy, InputIt begin, Size n, OutputIt output_begin);
804
805template <typename ExecutionPolicy,
806 typename Iterator,
807 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
808void
809destroy(ExecutionPolicy&& policy, Iterator first, Iterator last);
810
811template <typename ExecutionPolicy,
812 typename Iterator,
813 typename Size,
814 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
815Iterator
816destroy_n(ExecutionPolicy&& policy, Iterator first, Size n);
817
818} // namespace adl_barrier
819
820using namespace adl_barrier;
822
831template <typename T>
832void
834
844template <typename T>
845void
847
856
865
873template <typename T>
875size_bytes(T* array);
876
877} // namespace stdgpu
878
879#include <stdgpu/impl/memory_detail.h>
880
881#endif // STDGPU_MEMORY_H
const T * operator->() const
Returns a pointer to the managed object.
T & operator*()
Returns a reference to the managed object.
device_unique_object(Args &&... args)
Creates an object on the GPU (device)
device_unique_object(ExecutionPolicy &&policy, Args &&... args)
Creates an object on the GPU (device)
const T & operator*() const
Returns a reference to the managed object.
T * operator->()
Returns a pointer to the managed object.
A resource wrapper for managing device objects with automatic scope-based object destruction.
Definition: memory.h:247
device_unique_object(null_object_t)
Creates an empty unique object.
std::ptrdiff_t index64_t
std::ptrdiff_t
Definition: cstddef.h:48
index64_t get_deallocation_count(dynamic_memory_type memory_type)
Returns the total number of registered deallocations of a specific memory type.
T * createDeviceArray(const stdgpu::index64_t count, const T default_value=T())
Creates a new device array and initializes (fills) it with the given default value.
STDGPU_HOST_DEVICE T * construct_at(T *p, Args &&... args)
Destroys the value at the given pointer.
T * copyCreateHost2HostArray(const T *host_array, const stdgpu::index64_t count, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Creates and copies the given host array to the host.
index64_t size_bytes(T *array)
Finds the size (in bytes) of the given dynamically allocated array.
void destroyHostArray(T *&host_array)
Destroys the given host array.
OutputIt uninitialized_copy_n(ExecutionPolicy &&policy, InputIt begin, Size n, OutputIt output_begin)
Copies all elements of the input range to the output range using the copy constructor.
index64_t get_allocation_count(dynamic_memory_type memory_type)
Returns the total number of registered allocations of a specific memory type.
void uninitialized_fill(ExecutionPolicy &&policy, Iterator begin, Iterator end, const T &value)
Writes the given value to into the given range using the copy constructor.
T * createHostArray(const stdgpu::index64_t count, const T default_value=T())
Creates a new host array and initializes (fills) it with the given default value.
T * copyCreateHost2DeviceArray(const T *host_array, const stdgpu::index64_t count, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Creates and copies the given host array to the device.
void deregister_memory(T *p, index64_t n, dynamic_memory_type memory_type)
Deregisters the given memory block into the internal memory size manger.
dynamic_memory_type
The types of a dynamically allocated array.
Definition: memory.h:318
void register_memory(T *p, index64_t n, dynamic_memory_type memory_type)
Registers the given memory block into the internal memory size manger.
void destroy(ExecutionPolicy &&policy, Iterator first, Iterator last)
Destroys the range of values.
Iterator uninitialized_fill_n(ExecutionPolicy &&policy, Iterator begin, Size n, const T &value)
Writes the given value to into the given range using the copy constructor.
void copyHost2HostArray(const T *source_host_array, const stdgpu::index64_t count, T *destination_host_array, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Copies the given host array to the host.
Iterator destroy_n(ExecutionPolicy &&policy, Iterator first, Size n)
Destroys the range of values.
OutputIt uninitialized_copy(ExecutionPolicy &&policy, InputIt begin, InputIt end, OutputIt output_begin)
Copies all elements of the input range to the output range using the copy constructor.
dynamic_memory_type get_dynamic_memory_type(T *array)
Determines the dynamic memory type of the given array.
void copyDevice2DeviceArray(const T *source_device_array, const stdgpu::index64_t count, T *destination_device_array, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Copies the given device array to the device.
STDGPU_HOST_DEVICE void destroy_at(T *p)
Destroys the value at the given pointer.
T * copyCreateDevice2DeviceArray(const T *device_array, const stdgpu::index64_t count, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Creates and copies the given device array to the device.
STDGPU_HOST_DEVICE T * to_address(T *p) noexcept
Converts a potential fancy pointer to a raw pointer.
void copyHost2DeviceArray(const T *source_host_array, const stdgpu::index64_t count, T *destination_device_array, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Copies the given host array to the device.
MemoryCopy
The copy check states.
Definition: memory.h:90
void copyDevice2HostArray(const T *source_device_array, const stdgpu::index64_t count, T *destination_host_array, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Copies the given device array to the host.
T * copyCreateDevice2HostArray(const T *device_array, const stdgpu::index64_t count, const MemoryCopy check_safety=MemoryCopy::RANGE_CHECK)
Creates and copies the given device array to the host.
void destroyDeviceArray(T *&device_array)
Destroys the given device array.
constexpr null_object_t null_object
A constant to indicate an uninitialized unique object.
Definition: memory.h:238
#define STDGPU_HOST_DEVICE
Platform-independent host device function annotation.
Definition: platform.h:77
typename Allocator::value_type value_type
Definition: memory.h:494
static pointer allocate(Allocator &a, index_type n, const_void_pointer hint)
Allocates a memory block of the given size.
std::false_type propagate_on_container_copy_assignment
Definition: memory.h:506
static pointer allocate(Allocator &a, index_type n)
Allocates a memory block of the given size.
std::is_empty< Allocator > is_always_equal
Definition: memory.h:509
typename std::pointer_traits< pointer >::template rebind< const value_type > const_pointer
Definition: memory.h:497
value_type * pointer
Definition: memory.h:495
typename std::pointer_traits< pointer >::template rebind< const void > const_void_pointer
Definition: memory.h:501
static Allocator select_on_container_copy_construction(const Allocator &a)
Returns a copy of the allocator.
static void deallocate(Allocator &a, pointer p, index_type n)
Deallocates the given memory block.
typename std::allocator_traits< Allocator >::template rebind_alloc< T > rebind_alloc
Definition: memory.h:512
index64_t index_type
Definition: memory.h:505
static STDGPU_HOST_DEVICE index_type max_size(const Allocator &a) noexcept
Returns the maximum size that could be theoretically allocated.
static STDGPU_HOST_DEVICE void destroy(Allocator &a, T *p)
Destroys the object value at the given pointer.
static void deallocate_filled(ExecutionPolicy &&policy, Allocator &a, pointer p, index_type n)
Deallocates the given filled memory block.
std::false_type propagate_on_container_swap
Definition: memory.h:508
std::false_type propagate_on_container_move_assignment
Definition: memory.h:507
static STDGPU_HOST_DEVICE void construct(Allocator &a, T *p, Args &&... args)
Constructs an object value at the given pointer.
Allocator allocator_type
Definition: memory.h:493
static pointer allocate_filled(ExecutionPolicy &&policy, Allocator &a, index_type n, const value_type &default_value)
Allocates and fills a memory block of the given size.
typename std::pointer_traits< pointer >::difference_type difference_type
Definition: memory.h:504
typename std::pointer_traits< pointer >::template rebind< void > void_pointer
Definition: memory.h:499
A general allocator traitor.
Definition: memory.h:492
A type to indicate an uninitialized unique object.
Definition: memory.h:228
void deallocate(T *p, index64_t n)
Deallocates the given memory block.
T value_type
Definition: memory.h:342
T * allocate(index64_t n)
Allocates a memory block of the given size.
An allocator for device memory.
Definition: memory.h:341
static constexpr dynamic_memory_type memory_type
Dynamic memory type of allocations.
Definition: memory.h:347
safe_device_allocator() noexcept=default
Default constructor.
T value_type
Definition: memory.h:416
An allocator for host memory.
Definition: memory.h:415
safe_host_allocator() noexcept=default
Default constructor.