MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
device.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_DEVICE_HPP
13#define MFEM_DEVICE_HPP
14
15#include "enzyme.hpp"
16#include "globals.hpp"
17#include "mem_manager.hpp"
18
19#include <string>
20
21namespace mfem
22{
23
24/// MFEM backends.
25/** Individual backends will generally implement only a subset of the kernels
26 implemented by the default CPU backend. The goal of the backends is to
27 accelerate data-parallel portions of the code and they can use a device
28 memory space (e.g. GPUs) or share the memory space of the host (OpenMP). */
29struct Backend
30{
31 /** @brief In the documentation below, we use square brackets to indicate the
32 type of the backend: host or device. */
33 enum Id: unsigned long
34 {
35 /// [host] Default CPU backend: sequential execution on each MPI rank.
36 CPU = 1 << 0,
37 /// [host] OpenMP backend. Enabled when MFEM_USE_OPENMP = YES.
38 OMP = 1 << 1,
39 /// [device] CUDA backend. Enabled when MFEM_USE_CUDA = YES.
40 CUDA = 1 << 2,
41 /// [device] HIP backend. Enabled when MFEM_USE_HIP = YES.
42 HIP = 1 << 3,
43 /** @brief [host] RAJA CPU backend: sequential execution on each MPI rank.
44 Enabled when MFEM_USE_RAJA = YES. */
45 RAJA_CPU = 1 << 4,
46 /** @brief [host] RAJA OpenMP backend. Enabled when MFEM_USE_RAJA = YES
47 and MFEM_USE_OPENMP = YES. */
48 RAJA_OMP = 1 << 5,
49 /** @brief [device] RAJA CUDA backend. Enabled when MFEM_USE_RAJA = YES
50 and MFEM_USE_CUDA = YES. */
51 RAJA_CUDA = 1 << 6,
52 /** @brief [device] RAJA HIP backend. Enabled when MFEM_USE_RAJA = YES
53 and MFEM_USE_HIP = YES. */
54 RAJA_HIP = 1 << 7,
55 /** @brief [host] OCCA CPU backend: sequential execution on each MPI rank.
56 Enabled when MFEM_USE_OCCA = YES. */
57 OCCA_CPU = 1 << 8,
58 /// [host] OCCA OpenMP backend. Enabled when MFEM_USE_OCCA = YES.
59 OCCA_OMP = 1 << 9,
60 /** @brief [device] OCCA CUDA backend. Enabled when MFEM_USE_OCCA = YES
61 and MFEM_USE_CUDA = YES. */
62 OCCA_CUDA = 1 << 10,
63 /** @brief [host] CEED CPU backend. GPU backends can still be used, but
64 with expensive memory transfers. Enabled when MFEM_USE_CEED = YES. */
65 CEED_CPU = 1 << 11,
66 /** @brief [device] CEED CUDA backend working together with the CUDA
67 backend. Enabled when MFEM_USE_CEED = YES and MFEM_USE_CUDA = YES.
68 NOTE: The current default libCEED CUDA backend is non-deterministic! */
69 CEED_CUDA = 1 << 12,
70 /** @brief [device] CEED HIP backend working together with the HIP
71 backend. Enabled when MFEM_USE_CEED = YES and MFEM_USE_HIP = YES. */
72 CEED_HIP = 1 << 13,
73 /** @brief [device] Debug backend: host memory is READ/WRITE protected
74 while a device is in use. It allows to test the "device" code-path
75 (using separate host/device memory pools and host <-> device
76 transfers) without any GPU hardware. As 'DEBUG' is sometimes used
77 as a macro, `_DEVICE` has been added to avoid conflicts. */
78 DEBUG_DEVICE = 1 << 14
79 };
80
81 /** @brief Additional useful constants. For example, the *_MASK constants can
82 be used with Device::Allows(). */
83 enum
84 {
85 /// Number of backends: from (1 << 0) to (1 << (NUM_BACKENDS-1)).
87
88 /// Biwise-OR of all CPU backends
90 /// Biwise-OR of all CUDA backends
92 /// Biwise-OR of all HIP backends
94 /// Biwise-OR of all OpenMP backends
96 /// Bitwise-OR of all CEED backends
98 /// Biwise-OR of all device backends
100 /// Biwise-OR of all RAJA backends
102 /// Biwise-OR of all OCCA backends
104 };
105};
106
107
108/** @brief The MFEM Device class abstracts hardware devices such as GPUs, as
109 well as programming models such as CUDA, OCCA, RAJA and OpenMP. */
110/** This class represents a "virtual device" with the following properties:
111 - At most one object of this class can be constructed and that object is
112 controlled by its static methods.
113 - If no Device object is constructed, the static methods will use a default
114 global object which is never configured and always uses Backend::CPU.
115 - Once configured, the object cannot be re-configured during the program
116 lifetime.
117 - MFEM classes use this object to determine where (host or device) to
118 perform an operation and which backend implementation to use.
119 - Multiple backends can be configured at the same time; currently, a fixed
120 priority order is used to select a specific backend from the list of
121 configured backends. See the Backend class and the Configure() method in
122 this class for details. */
124{
125private:
126 friend class MemoryManager;
127
128 static bool device_env, mem_host_env, mem_device_env, mem_types_set;
129 MFEM_ENZYME_INACTIVE static MFEM_EXPORT Device device_singleton;
130
131 int dev = 0; ///< Device ID of the configured device.
132 int ngpu = -1; ///< Number of detected devices; -1: not initialized.
133
134 /// Bitwise-OR of all configured backends.
135 unsigned long backends = Backend::CPU;
136
137 /// Set to true during configuration, except in 'device_singleton'.
138 bool destroy_mm = false;
139 bool mpi_gpu_aware = false;
140
141 MemoryType host_mem_type = MemoryType::HOST; ///< Current Host MemoryType
142 MemoryClass host_mem_class = MemoryClass::HOST; ///< Current Host MemoryClass
143
144 /// Current Device MemoryType
145 MemoryType device_mem_type = MemoryType::HOST;
146 /// Current Device MemoryClass
147 MemoryClass device_mem_class = MemoryClass::HOST;
148
149 // Delete copy constructor and copy assignment.
150 Device(const Device &) = delete;
151 Device &operator=(const Device &) = delete;
152
153 // Access the Device singleton.
154 static Device& Get() { return device_singleton; }
155
156 /// Setup switcher based on configuration settings.
157 void Setup(const std::string &device_option, const int device_id);
158
159 /// Configure host/device MemoryType/MemoryClass.
160 void UpdateMemoryTypeAndClass(const std::string &device_option);
161
162 /// Configure the backends to include @a b.
163 void MarkBackend(Backend::Id b) { backends |= b; }
164
165public:
166 /** @brief Default constructor. Unless Configure() is called later, the
167 default Backend::CPU will be used. */
168 /** @note At most one Device object can be constructed during the lifetime of
169 a program.
170 @note This object should be destroyed after all other MFEM objects that
171 use the Device are destroyed. */
172 Device();
173
174 /** @brief Construct a Device and configure it based on the @a device string.
175 See Configure() for more details. */
176 /** @note At most one Device object can be constructed during the lifetime of
177 a program.
178 @note This object should be destroyed after all other MFEM objects that
179 use the Device are destroyed. */
180 Device(const std::string &device, const int device_id = 0)
181 { Configure(device, device_id); }
182
183 /// Destructor.
184 ~Device();
185
186 /// Configure the Device backends.
187 /** The string parameter @a device must be a comma-separated list of backend
188 string names (see below). The @a device_id argument specifies the ID of
189 the actual devices (e.g. GPU) to use.
190 - The available backends are described by the Backend class.
191 - The string name of a backend is the lowercase version of the
192 Backend::Id enumeration constant with '_' replaced by '-', e.g. the
193 string name of 'RAJA_CPU' is 'raja-cpu'. The string name of the debug
194 backend (Backend::Id 'DEBUG_DEVICE') is exceptionally set to 'debug'.
195 - The 'cpu' backend is always enabled with lowest priority.
196 - The current backend priority from highest to lowest is:
197 'ceed-cuda', 'occa-cuda', 'raja-cuda', 'cuda',
198 'ceed-hip', 'hip', 'debug',
199 'occa-omp', 'raja-omp', 'omp',
200 'ceed-cpu', 'occa-cpu', 'raja-cpu', 'cpu'.
201 - The following backend aliases are also available: 'ceed-gpu',
202 'occa-gpu', 'raja-gpu', and 'gpu' where they alias their respective
203 '*-cuda' or '*-hip' backends depending on the MFEM build-time
204 configuration.
205 - Multiple backends can be configured at the same time.
206 - Only one 'occa-*' backend can be configured at a time.
207 - The backend 'occa-cuda' enables the 'cuda' backend unless 'raja-cuda'
208 is already enabled.
209 - The backend 'occa-omp' enables the 'omp' backend (if MFEM was built
210 with MFEM_USE_OPENMP=YES) unless 'raja-omp' is already enabled.
211 - Only one 'ceed-*' backend can be configured at a time.
212 - The backend 'ceed-cpu' delegates to a libCEED CPU backend the setup and
213 evaluation of the operator.
214 - The backend 'ceed-cuda' delegates to a libCEED CUDA backend the setup
215 and evaluation of operators and enables the 'cuda' backend to avoid
216 transfers between host and device.
217 - The backend 'ceed-hip' delegates to a libCEED HIP backend the setup
218 and evaluation of operators and enables the 'hip' backend to avoid
219 transfers between host and device.
220 - The 'debug' backend should not be combined with other device backends.
221
222 @note If the device is actually enabled, this method will also update the
223 current host/device MemoryType and MemoryClass. */
224 void Configure(const std::string &device, const int device_id = 0);
225
226 /// Set the default host and device MemoryTypes, @a h_mt and @a d_mt.
227 /** The host and device MemoryTypes are also set to be dual to each other.
228
229 These two MemoryType%s are used by most MFEM classes when allocating
230 memory used on host and device, respectively.
231
232 This method can only be called before Device construction and
233 configuration, and the specified memory types must be compatible with
234 the subsequent Device configuration. */
235 static void SetMemoryTypes(MemoryType h_mt, MemoryType d_mt);
236
237 /// Print the configuration of the MFEM virtual device object.
238 void Print(std::ostream &os = mfem::out);
239
240 /// Return true if Configure() has been called previously.
241 static inline bool IsConfigured() { return Get().ngpu >= 0; }
242
243 /// Return true if an actual device (e.g. GPU) has been configured.
244 static inline bool IsAvailable() { return Get().ngpu > 0; }
245
246 /// Return true if any backend other than Backend::CPU is enabled.
247 static inline bool IsEnabled() { return Get().backends & ~(Backend::CPU); }
248
249 /// The opposite of IsEnabled().
250 static inline bool IsDisabled() { return !IsEnabled(); }
251
252 /// Get the device ID of the configured device.
253 static inline int GetId() { return Get().dev; }
254
255 /// Get the number of available devices (may be called before configuration).
256 static int GetDeviceCount();
257
258 /** @brief Return true if any of the backends in the backend mask, @a b_mask,
259 are allowed. */
260 /** This method can be used with any of the Backend::Id constants, the
261 Backend::*_MASK, or combinations of those. */
262 static inline bool Allows(unsigned long b_mask)
263 { return Get().backends & b_mask; }
264
265 /** @brief Get the current Host MemoryType. This is the MemoryType used by
266 most MFEM classes when allocating memory used on the host.
267 */
268 static inline MemoryType GetHostMemoryType() { return Get().host_mem_type; }
269
270 /** @brief Get the current Host MemoryClass. This is the MemoryClass used
271 by most MFEM host Memory objects. */
272 static inline MemoryClass GetHostMemoryClass() { return Get().host_mem_class; }
273
274 /** @brief Get the current Device MemoryType. This is the MemoryType used by
275 most MFEM classes when allocating memory to be used with device kernels.
276 */
277 static inline MemoryType GetDeviceMemoryType() { return Get().device_mem_type; }
278
279 /// (DEPRECATED) Equivalent to GetDeviceMemoryType().
280 /** @deprecated Use GetDeviceMemoryType() instead. */
281 static inline MemoryType GetMemoryType() { return Get().device_mem_type; }
282
283 /** @brief Get the current Device MemoryClass. This is the MemoryClass used
284 by most MFEM device kernels to access Memory objects. */
285 static inline MemoryClass GetDeviceMemoryClass() { return Get().device_mem_class; }
286
287 /// (DEPRECATED) Equivalent to GetDeviceMemoryClass().
288 /** @deprecated Use GetDeviceMemoryClass() instead. */
289 static inline MemoryClass GetMemoryClass() { return Get().device_mem_class; }
290
291 /** @brief Manually set the status of GPU-aware MPI flag for use in MPI
292 communication routines which have optimized implementations for device
293 buffers. */
294 static void SetGPUAwareMPI(const bool force = true)
295 { Get().mpi_gpu_aware = force; }
296
297 /// Get the status of GPU-aware MPI flag.
298 static bool GetGPUAwareMPI() { return Get().mpi_gpu_aware; }
299
300 /** Query the device driver for what memory type a given @a ptr is allocated
301 * with. */
302 static MemoryType QueryMemoryType(const void* ptr);
303
304 /** @brief The number of hardware compute units/streaming multiprocessors
305 available on a given compute device @a device_id. */
306 static int NumMultiprocessors(int device_id);
307
308 /// Same as NumMultiprocessors(int), for the currently active device.
309 static int NumMultiprocessors();
310
311 /** @brief The number of threads in a warp on a given compute device
312 @a device_id. */
313 static int WarpSize(int device_id);
314
315 /// Same as WarpSize(int), for the currently active device.
316 static int WarpSize();
317
318 /** @brief Gets the @a free and @a total memory on the device. */
319 static void DeviceMem(size_t *free, size_t *total);
320};
321
322
323// Inline Memory access functions using the mfem::Device DeviceMemoryClass or
324// the mfem::Device HostMemoryClass.
325
326/** @brief Return the memory class to be used by the functions Read(), Write(),
327 and ReadWrite(), while setting the device use flag in @a mem, if @a on_dev
328 is true. */
329template <typename T>
330inline MemoryClass GetMemoryClass(const Memory<T> &mem, bool on_dev)
331{
332 if (!on_dev)
333 {
335 }
336 else
337 {
338 mem.UseDevice(true);
340 }
341}
342
343/** @brief Get a pointer for read access to @a mem with the mfem::Device's
344 DeviceMemoryClass, if @a on_dev = true, or the mfem::Device's
345 HostMemoryClass, otherwise. */
346/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
347template <typename T>
348inline const T *Read(const Memory<T> &mem, int size, bool on_dev = true)
349{
350 return mem.Read(GetMemoryClass(mem, on_dev), size);
351}
352
353/** @brief Shortcut to Read(const Memory<T> &mem, int size, false) */
354template <typename T>
355inline const T *HostRead(const Memory<T> &mem, int size)
356{
357 return mfem::Read(mem, size, false);
358}
359
360/** @brief Get a pointer for write access to @a mem with the mfem::Device's
361 DeviceMemoryClass, if @a on_dev = true, or the mfem::Device's
362 HostMemoryClass, otherwise. */
363/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
364template <typename T>
365inline T *Write(Memory<T> &mem, int size, bool on_dev = true)
366{
367 return mem.Write(GetMemoryClass(mem, on_dev), size);
368}
369
370/** @brief Shortcut to Write(const Memory<T> &mem, int size, false) */
371template <typename T>
372inline T *HostWrite(Memory<T> &mem, int size)
373{
374 return mfem::Write(mem, size, false);
375}
376
377/** @brief Get a pointer for read+write access to @a mem with the mfem::Device's
378 DeviceMemoryClass, if @a on_dev = true, or the mfem::Device's
379 HostMemoryClass, otherwise. */
380/** Also, if @a on_dev = true, the device flag of @a mem will be set. */
381template <typename T>
382inline T *ReadWrite(Memory<T> &mem, int size, bool on_dev = true)
383{
384 return mem.ReadWrite(GetMemoryClass(mem, on_dev), size);
385}
386
387/** @brief Shortcut to ReadWrite(Memory<T> &mem, int size, false) */
388template <typename T>
389inline T *HostReadWrite(Memory<T> &mem, int size)
390{
391 return mfem::ReadWrite(mem, size, false);
392}
393
394} // namespace mfem
395
396#endif // MFEM_DEVICE_HPP
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:124
static MemoryType GetHostMemoryType()
Get the current Host MemoryType. This is the MemoryType used by most MFEM classes when allocating mem...
Definition device.hpp:268
~Device()
Destructor.
Definition device.cpp:156
static MemoryClass GetMemoryClass()
(DEPRECATED) Equivalent to GetDeviceMemoryClass().
Definition device.hpp:289
static void DeviceMem(size_t *free, size_t *total)
Gets the free and total memory on the device.
Definition device.cpp:700
static MemoryClass GetHostMemoryClass()
Get the current Host MemoryClass. This is the MemoryClass used by most MFEM host Memory objects.
Definition device.hpp:272
void Configure(const std::string &device, const int device_id=0)
Configure the Device backends.
Definition device.cpp:189
static bool IsAvailable()
Return true if an actual device (e.g. GPU) has been configured.
Definition device.hpp:244
static void SetGPUAwareMPI(const bool force=true)
Manually set the status of GPU-aware MPI flag for use in MPI communication routines which have optimi...
Definition device.hpp:294
static MemoryType GetMemoryType()
(DEPRECATED) Equivalent to GetDeviceMemoryType().
Definition device.hpp:281
static int NumMultiprocessors()
Same as NumMultiprocessors(int), for the currently active device.
Definition device.cpp:736
static bool IsConfigured()
Return true if Configure() has been called previously.
Definition device.hpp:241
static MemoryType QueryMemoryType(const void *ptr)
Definition device.cpp:618
void Print(std::ostream &os=mfem::out)
Print the configuration of the MFEM virtual device object.
Definition device.cpp:317
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
Definition device.hpp:262
Device(const std::string &device, const int device_id=0)
Construct a Device and configure it based on the device string. See Configure() for more details.
Definition device.hpp:180
static void SetMemoryTypes(MemoryType h_mt, MemoryType d_mt)
Set the default host and device MemoryTypes, h_mt and d_mt.
Definition device.cpp:294
static bool GetGPUAwareMPI()
Get the status of GPU-aware MPI flag.
Definition device.hpp:298
static MemoryClass GetDeviceMemoryClass()
Get the current Device MemoryClass. This is the MemoryClass used by most MFEM device kernels to acces...
Definition device.hpp:285
static int GetId()
Get the device ID of the configured device.
Definition device.hpp:253
static int WarpSize()
Same as WarpSize(int), for the currently active device.
Definition device.cpp:764
static int GetDeviceCount()
Get the number of available devices (may be called before configuration).
Definition device.cpp:425
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
Definition device.hpp:247
Device()
Default constructor. Unless Configure() is called later, the default Backend::CPU will be used.
Definition device.cpp:74
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
Definition device.hpp:277
static bool IsDisabled()
The opposite of IsEnabled().
Definition device.hpp:250
Class used by MFEM to store pointers to host and/or device memory.
T * Write(MemoryClass mc, int size)
Get write-only access to the memory with the given MemoryClass.
T * ReadWrite(MemoryClass mc, int size)
Get read-write access to the memory with the given MemoryClass.
bool UseDevice() const
Read the internal device flag.
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
real_t b
Definition lissajous.cpp:42
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:348
MemoryClass GetMemoryClass(const Memory< T > &mem, bool on_dev)
Return the memory class to be used by the functions Read(), Write(), and ReadWrite(),...
Definition device.hpp:330
T * HostReadWrite(Memory< T > &mem, int size)
Shortcut to ReadWrite(Memory<T> &mem, int size, false)
Definition device.hpp:389
const T * HostRead(const Memory< T > &mem, int size)
Shortcut to Read(const Memory<T> &mem, int size, false)
Definition device.hpp:355
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device's DeviceMemoryClass, if on_dev = true,...
Definition device.hpp:365
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
MemoryClass
Memory classes identify sets of memory types.
T * ReadWrite(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read+write access to mem with the mfem::Device's DeviceMemoryClass,...
Definition device.hpp:382
T * HostWrite(Memory< T > &mem, int size)
Shortcut to Write(const Memory<T> &mem, int size, false)
Definition device.hpp:372
MemoryType
Memory types supported by MFEM.
@ HOST
Host memory; using new[] and delete[].
MFEM backends.
Definition device.hpp:30
Id
In the documentation below, we use square brackets to indicate the type of the backend: host or devic...
Definition device.hpp:34
@ RAJA_OMP
[host] RAJA OpenMP backend. Enabled when MFEM_USE_RAJA = YES and MFEM_USE_OPENMP = YES.
Definition device.hpp:48
@ RAJA_CUDA
[device] RAJA CUDA backend. Enabled when MFEM_USE_RAJA = YES and MFEM_USE_CUDA = YES.
Definition device.hpp:51
@ DEBUG_DEVICE
[device] Debug backend: host memory is READ/WRITE protected while a device is in use....
Definition device.hpp:78
@ RAJA_CPU
[host] RAJA CPU backend: sequential execution on each MPI rank. Enabled when MFEM_USE_RAJA = YES.
Definition device.hpp:45
@ OMP
[host] OpenMP backend. Enabled when MFEM_USE_OPENMP = YES.
Definition device.hpp:38
@ HIP
[device] HIP backend. Enabled when MFEM_USE_HIP = YES.
Definition device.hpp:42
@ OCCA_OMP
[host] OCCA OpenMP backend. Enabled when MFEM_USE_OCCA = YES.
Definition device.hpp:59
@ RAJA_HIP
[device] RAJA HIP backend. Enabled when MFEM_USE_RAJA = YES and MFEM_USE_HIP = YES.
Definition device.hpp:54
@ OCCA_CUDA
[device] OCCA CUDA backend. Enabled when MFEM_USE_OCCA = YES and MFEM_USE_CUDA = YES.
Definition device.hpp:62
@ CEED_CPU
[host] CEED CPU backend. GPU backends can still be used, but with expensive memory transfers....
Definition device.hpp:65
@ OCCA_CPU
[host] OCCA CPU backend: sequential execution on each MPI rank. Enabled when MFEM_USE_OCCA = YES.
Definition device.hpp:57
@ CEED_CUDA
[device] CEED CUDA backend working together with the CUDA backend. Enabled when MFEM_USE_CEED = YES a...
Definition device.hpp:69
@ CPU
[host] Default CPU backend: sequential execution on each MPI rank.
Definition device.hpp:36
@ CUDA
[device] CUDA backend. Enabled when MFEM_USE_CUDA = YES.
Definition device.hpp:40
@ CEED_HIP
[device] CEED HIP backend working together with the HIP backend. Enabled when MFEM_USE_CEED = YES and...
Definition device.hpp:72
@ RAJA_MASK
Biwise-OR of all RAJA backends.
Definition device.hpp:101
@ DEVICE_MASK
Biwise-OR of all device backends.
Definition device.hpp:99
@ CEED_MASK
Bitwise-OR of all CEED backends.
Definition device.hpp:97
@ OCCA_MASK
Biwise-OR of all OCCA backends.
Definition device.hpp:103
@ HIP_MASK
Biwise-OR of all HIP backends.
Definition device.hpp:93
@ CPU_MASK
Biwise-OR of all CPU backends.
Definition device.hpp:89
@ NUM_BACKENDS
Number of backends: from (1 << 0) to (1 << (NUM_BACKENDS-1)).
Definition device.hpp:86
@ CUDA_MASK
Biwise-OR of all CUDA backends.
Definition device.hpp:91
@ OMP_MASK
Biwise-OR of all OpenMP backends.
Definition device.hpp:95