Cuda battery library
Loading...
Searching...
No Matches
memory.hpp
Go to the documentation of this file.
1// Copyright 2022 Pierre Talbot
2
3#ifndef CUDA_BATTERY_MEMORY_HPP
4#define CUDA_BATTERY_MEMORY_HPP
5
6/** \file memory.hpp
7 * An abstraction of memory load and store useful to write a single version of an algorithm working either sequentially or in parallel, and on CPU or GPU.
8 * Note that these classes are mainly designed to work with a relaxed memory ordering; we are unsure of their applicability to other kinds of memory ordering.
9 */
10
11#include <cassert>
12#include <type_traits>
13#include <utility>
14
15#ifdef __CUDACC__
16 #include <cuda/atomic>
17#else
18 #include <atomic>
19#endif
20
21#include "utility.hpp"
22
23namespace battery {
24
25/** Represent the memory of a variable that cannot be accessed by multiple threads. */
26template <bool read_only>
27class memory {
28public:
29 template <class T> using atomic_type = T;
30
31 /** Indicate this memory is written by a single thread. */
32 constexpr static const bool sequential = true;
33
34public:
35 template <class T>
36 CUDA INLINE static constexpr T load(const atomic_type<T>& a) {
37 return a;
38 }
39
40 template <class T>
41 CUDA INLINE static constexpr std::enable_if_t<!read_only, void> store(atomic_type<T>& a, T v) {
42 a = v;
43 }
44
45 template <class T>
46 CUDA INLINE static constexpr std::enable_if_t<!read_only, T> exchange(atomic_type<T>& a, T v) {
47 return std::exchange(a, std::move(v));
48 }
49};
50
53
54#ifdef __CUDACC__
55
56/** Memory load and store operations relative to a cuda scope (per-thread, block, grid, ...) and given a certain memory order (by default relaxed). */
57template <cuda::thread_scope scope, cuda::memory_order mem_order = cuda::memory_order_relaxed>
58class atomic_memory_scoped {
59public:
60 template <class T> using atomic_type = cuda::atomic<T, scope>;
61 constexpr static const bool sequential = false;
62
63 template <class T>
64 CUDA INLINE static T load(const atomic_type<T>& a) {
65 return a.load(mem_order);
66 }
67
68 template <class T>
69 CUDA INLINE static void store(atomic_type<T>& a, T v) {
70 a.store(v, mem_order);
71 }
72
73 template <class T>
74 CUDA INLINE static T exchange(atomic_type<T>& a, T v) {
75 return a.exchange(v, mem_order);
76 }
77};
78
79using atomic_memory_block = atomic_memory_scoped<cuda::thread_scope_block>;
80using atomic_memory_grid = atomic_memory_scoped<cuda::thread_scope_device>;
81using atomic_memory_multi_grid = atomic_memory_scoped<cuda::thread_scope_system>;
82
83#endif // __CUDACC__
84
85#ifdef __CUDACC__
86 /// @private
87 namespace impl {
88 template <class T>
89 using atomic_t = cuda::std::atomic<T>;
90 }
91 /// @private
92 using memory_order = cuda::std::memory_order;
93 /// @private
94 constexpr memory_order memory_order_relaxed = cuda::std::memory_order_relaxed;
95 /// @private
96 constexpr memory_order memory_order_seq_cst = cuda::std::memory_order_seq_cst;
97#else
98 /// @private
99 namespace impl {
100 template <class T>
101 using atomic_t = std::atomic<T>;
102 }
103 /// @private
104 using memory_order = std::memory_order;
105 /// @private
106 constexpr memory_order memory_order_relaxed = std::memory_order_relaxed;
107 /// @private
108 constexpr memory_order memory_order_seq_cst = std::memory_order_seq_cst;
109#endif
110
111/** Use the standard C++ atomic type, either provided by libcudacxx if we compile with a CUDA compiler, or through the STL otherwise. */
112template <memory_order mem_order = memory_order_relaxed>
114public:
115 template <class T> using atomic_type = impl::atomic_t<T>;
116 constexpr static const bool sequential = false;
117
118 template <class T>
119 CUDA INLINE static T load(const atomic_type<T>& a) {
120 return a.load(mem_order);
121 }
122
123 template <class T>
124 CUDA INLINE static void store(atomic_type<T>& a, T v) {
125 a.store(v, mem_order);
126 }
127
128 template <class T>
129 CUDA INLINE static T exchange(atomic_type<T>& a, T v) {
130 return a.exchange(v, mem_order);
131 }
132};
133
134}
135
136#endif
Definition memory.hpp:113
CUDA static INLINE void store(atomic_type< T > &a, T v)
Definition memory.hpp:124
CUDA static INLINE T load(const atomic_type< T > &a)
Definition memory.hpp:119
static constexpr const bool sequential
Definition memory.hpp:116
CUDA static INLINE T exchange(atomic_type< T > &a, T v)
Definition memory.hpp:129
impl::atomic_t< T > atomic_type
Definition memory.hpp:115
Definition memory.hpp:27
CUDA static INLINE constexpr T load(const atomic_type< T > &a)
Definition memory.hpp:36
static constexpr const bool sequential
Definition memory.hpp:32
T atomic_type
Definition memory.hpp:29
CUDA static INLINE constexpr std::enable_if_t<!read_only, void > store(atomic_type< T > &a, T v)
Definition memory.hpp:41
CUDA static INLINE constexpr std::enable_if_t<!read_only, T > exchange(atomic_type< T > &a, T v)
Definition memory.hpp:46
Definition algorithm.hpp:10
#define INLINE
Definition utility.hpp:63
#define CUDA
Definition utility.hpp:59