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 <functional>
29#include <memory>
30#include <type_traits>
31
32#include <stdgpu/config.h>
33#include <stdgpu/cstddef.h>
34#include <stdgpu/execution.h>
35#include <stdgpu/platform.h>
36#include <stdgpu/type_traits.h>
37
43{
44 HOST,
45 DEVICE
46};
47
57template <typename T>
58[[nodiscard]] T*
59createDeviceArray(const stdgpu::index64_t count, const T default_value = T());
60
70template <typename T>
71[[nodiscard]] T*
72createHostArray(const stdgpu::index64_t count, const T default_value = T());
73
84template <typename T>
85[[nodiscard]] T*
87 const T default_value = T(),
88 const Initialization initialize_on = Initialization::DEVICE);
89
96template <typename T>
97void
98destroyDeviceArray(T*& device_array);
99
106template <typename T>
107void
108destroyHostArray(T*& host_array);
109
116template <typename T>
117void
118destroyManagedArray(T*& managed_array);
119
124enum class MemoryCopy
125{
126 NO_CHECK,
129};
130
141template <typename T>
142[[nodiscard]] T*
143copyCreateDevice2HostArray(const T* device_array,
144 const stdgpu::index64_t count,
145 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
146
157template <typename T>
158[[nodiscard]] T*
159copyCreateHost2DeviceArray(const T* host_array,
160 const stdgpu::index64_t count,
161 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
162
173template <typename T>
174[[nodiscard]] T*
175copyCreateHost2HostArray(const T* host_array,
176 const stdgpu::index64_t count,
177 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
178
189template <typename T>
190[[nodiscard]] T*
191copyCreateDevice2DeviceArray(const T* device_array,
192 const stdgpu::index64_t count,
193 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
194
205template <typename T>
206void
207copyDevice2HostArray(const T* source_device_array,
208 const stdgpu::index64_t count,
209 T* destination_host_array,
210 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
211
222template <typename T>
223void
224copyHost2DeviceArray(const T* source_host_array,
225 const stdgpu::index64_t count,
226 T* destination_device_array,
227 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
228
239template <typename T>
240void
241copyHost2HostArray(const T* source_host_array,
242 const stdgpu::index64_t count,
243 T* destination_host_array,
244 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
245
256template <typename T>
257void
258copyDevice2DeviceArray(const T* source_device_array,
259 const stdgpu::index64_t count,
260 T* destination_device_array,
261 const MemoryCopy check_safety = MemoryCopy::RANGE_CHECK);
262
263namespace stdgpu
264{
265
271{
273 constexpr explicit null_object_t(int /* unspecified */) { }
275};
276
281inline constexpr null_object_t null_object{ 0 };
282
288template <typename T>
290{
291public:
295 explicit device_unique_object(null_object_t /*null_object*/);
296
302 template <typename... Args>
303 explicit device_unique_object(Args&&... args);
304
312 template <typename ExecutionPolicy,
313 typename... Args,
314 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
315 explicit device_unique_object(ExecutionPolicy&& policy, Args&&... args);
316
321 const T*
322 operator->() const;
323
328 T*
330
335 const T&
336 operator*() const;
337
342 T&
344
349 explicit operator bool() const;
350
351private:
352 std::unique_ptr<T, std::function<void(T*)>> _object;
353};
354
360{
361 host,
362 device,
363 managed,
365 invalid
366};
367
374template <typename T>
377
383template <typename T>
385{
386 using value_type = T;
392
396 safe_device_allocator() noexcept = default;
397
401 ~safe_device_allocator() noexcept = default;
402
407
413 template <typename U>
414 explicit safe_device_allocator(const safe_device_allocator<U>& other) noexcept;
415
421 operator=(const safe_device_allocator&) noexcept = default;
422
427
433 operator=(safe_device_allocator&&) noexcept = default;
434
440 [[nodiscard]] T*
442
448 void
450};
451
457template <typename T>
459{
460 using value_type = T;
466
470 safe_host_allocator() noexcept = default;
471
475 ~safe_host_allocator() noexcept = default;
476
480 safe_host_allocator(const safe_host_allocator&) noexcept = default;
481
487 template <typename U>
488 explicit safe_host_allocator(const safe_host_allocator<U>& other) noexcept;
489
495 operator=(const safe_host_allocator&) noexcept = default;
496
501
507 operator=(safe_host_allocator&&) noexcept = default;
508
514 [[nodiscard]] T*
516
522 void
524};
525
531template <typename T>
533{
534 using value_type = T;
540
544 safe_managed_allocator() noexcept = default;
545
549 ~safe_managed_allocator() noexcept = default;
550
555
561 template <typename U>
562 explicit safe_managed_allocator(const safe_managed_allocator<U>& other) noexcept;
563
569 operator=(const safe_managed_allocator&) noexcept = default;
570
575
581 operator=(safe_managed_allocator&&) noexcept = default;
582
588 [[nodiscard]] T*
590
596 void
598};
599
608template <typename Allocator>
610{
611 using allocator_type = Allocator;
612 using value_type = typename Allocator::value_type;
614 using const_pointer = typename std::pointer_traits<pointer>::template rebind<
615 const value_type>;
616 using void_pointer = typename std::pointer_traits<pointer>::template rebind<
617 void>;
618 using const_void_pointer = typename std::pointer_traits<pointer>::template rebind<
619 const void>;
621 typename std::pointer_traits<pointer>::difference_type;
626 using propagate_on_container_swap = std::false_type;
627 using is_always_equal = std::is_empty<Allocator>;
628 template <typename T>
629 using rebind_alloc = typename std::allocator_traits<Allocator>::template rebind_alloc<
630 T>;
631 template <typename T>
640 [[nodiscard]] static pointer
641 allocate(Allocator& a, index_type n);
642
650 [[nodiscard]] static pointer
651 allocate(Allocator& a, index_type n, const_void_pointer hint);
652
659 static void
660 deallocate(Allocator& a, pointer p, index_type n);
661
671 template <typename ExecutionPolicy,
672 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
673 [[nodiscard]] static pointer
674 allocate_filled(ExecutionPolicy&& policy, Allocator& a, index_type n, const value_type& default_value);
675
684 template <typename ExecutionPolicy,
685 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
686 static void
687 deallocate_filled(ExecutionPolicy&& policy, Allocator& a, pointer p, index_type n);
688
697 template <typename T, class... Args>
698 static STDGPU_HOST_DEVICE void
699 construct(Allocator& a, T* p, Args&&... args);
700
707 template <typename T>
708 static STDGPU_HOST_DEVICE void
709 destroy(Allocator& a, T* p);
710
717 max_size(const Allocator& a) noexcept;
718
724 static Allocator
726};
727
735template <typename T>
737to_address(T* p) noexcept;
738
746template <typename Ptr>
748to_address(const Ptr& p) noexcept;
749
759template <typename T, typename... Args>
761construct_at(T* p, Args&&... args);
762
769template <typename T>
772
773#ifdef STDGPU_RUN_DOXYGEN
774
786template <typename ExecutionPolicy,
787 typename Iterator,
788 typename T,
789 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
790void
791uninitialized_fill(ExecutionPolicy&& policy, Iterator begin, Iterator end, const T& value);
792
806template <typename ExecutionPolicy,
807 typename Iterator,
808 typename Size,
809 typename T,
810 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
811Iterator
812uninitialized_fill_n(ExecutionPolicy&& policy, Iterator begin, Size n, const T& value);
813
826template <typename ExecutionPolicy,
827 typename InputIt,
828 typename OutputIt,
829 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
830OutputIt
831uninitialized_copy(ExecutionPolicy&& policy, InputIt begin, InputIt end, OutputIt output_begin);
832
846template <typename ExecutionPolicy,
847 typename InputIt,
848 typename Size,
849 typename OutputIt,
850 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
851OutputIt
852uninitialized_copy_n(ExecutionPolicy&& policy, InputIt begin, Size n, OutputIt output_begin);
853
863template <typename ExecutionPolicy,
864 typename Iterator,
865 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
866void
867destroy(ExecutionPolicy&& policy, Iterator first, Iterator last);
868
880template <typename ExecutionPolicy,
881 typename Iterator,
882 typename Size,
883 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
884Iterator
885destroy_n(ExecutionPolicy&& policy, Iterator first, Size n);
886
887#endif
888
890namespace adl_barrier
891{
892
893template <typename ExecutionPolicy,
894 typename Iterator,
895 typename T,
896 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
897void
898uninitialized_fill(ExecutionPolicy&& policy, Iterator begin, Iterator end, const T& value);
899
900template <typename ExecutionPolicy,
901 typename Iterator,
902 typename Size,
903 typename T,
904 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
905Iterator
906uninitialized_fill_n(ExecutionPolicy&& policy, Iterator begin, Size n, const T& value);
907
908template <typename ExecutionPolicy,
909 typename InputIt,
910 typename OutputIt,
911 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
912OutputIt
913uninitialized_copy(ExecutionPolicy&& policy, InputIt begin, InputIt end, OutputIt output_begin);
914
915template <typename ExecutionPolicy,
916 typename InputIt,
917 typename Size,
918 typename OutputIt,
919 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
920OutputIt
921uninitialized_copy_n(ExecutionPolicy&& policy, InputIt begin, Size n, OutputIt output_begin);
922
923template <typename ExecutionPolicy,
924 typename Iterator,
925 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
926void
927destroy(ExecutionPolicy&& policy, Iterator first, Iterator last);
928
929template <typename ExecutionPolicy,
930 typename Iterator,
931 typename Size,
932 STDGPU_DETAIL_OVERLOAD_IF(is_execution_policy_v<remove_cvref_t<ExecutionPolicy>>)>
933Iterator
934destroy_n(ExecutionPolicy&& policy, Iterator first, Size n);
935
936} // namespace adl_barrier
937
938using namespace adl_barrier;
940
949template <typename T>
950void
952
962template <typename T>
963void
965
974
983
991template <typename T>
993size_bytes(T* array);
994
995} // namespace stdgpu
996
997#include <stdgpu/impl/memory_detail.h>
998
999#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:290
device_unique_object(null_object_t)
Creates an empty unique object.
std::ptrdiff_t index64_t
std::ptrdiff_t
Definition: cstddef.h:48
T * createManagedArray(const stdgpu::index64_t count, const T default_value=T(), const Initialization initialize_on=Initialization::DEVICE)
Creates a new managed array and initializes (fills) it with the given default value.
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.
MemoryCopy
The copy check states.
Definition: memory.h:125
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 destroyManagedArray(T *&managed_array)
Destroys the given managed array.
void deregister_memory(T *p, index64_t n, dynamic_memory_type memory_type)
Deregisters the given memory block into the internal memory size manger.
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.
Initialization
The place to initialize the created array.
Definition: memory.h:43
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.
dynamic_memory_type
The types of a dynamically allocated array.
Definition: memory.h:360
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.
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:281
#define STDGPU_HOST_DEVICE
Platform-independent host device function annotation.
Definition: platform.h:77
typename Allocator::value_type value_type
Definition: memory.h:612
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:624
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:627
typename std::pointer_traits< pointer >::template rebind< const value_type > const_pointer
Definition: memory.h:615
value_type * pointer
Definition: memory.h:613
typename std::pointer_traits< pointer >::template rebind< const void > const_void_pointer
Definition: memory.h:619
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:630
index64_t index_type
Definition: memory.h:623
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:626
std::false_type propagate_on_container_move_assignment
Definition: memory.h:625
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:611
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:622
typename std::pointer_traits< pointer >::template rebind< void > void_pointer
Definition: memory.h:617
A general allocator traitor.
Definition: memory.h:610
A type to indicate an uninitialized unique object.
Definition: memory.h:271
void deallocate(T *p, index64_t n)
Deallocates the given memory block.
T value_type
Definition: memory.h:386
T * allocate(index64_t n)
Allocates a memory block of the given size.
An allocator for device memory.
Definition: memory.h:385
static constexpr dynamic_memory_type memory_type
Dynamic memory type of allocations.
Definition: memory.h:391
safe_device_allocator() noexcept=default
Default constructor.
T value_type
Definition: memory.h:460
An allocator for host memory.
Definition: memory.h:459
safe_host_allocator() noexcept=default
Default constructor.
T value_type
Definition: memory.h:534
An allocator for managed memory.
Definition: memory.h:533
safe_managed_allocator() noexcept=default
Default constructor.