30 #ifndef SACADO_DYNAMICARRAYTRAITS_HPP
31 #define SACADO_DYNAMICARRAYTRAITS_HPP
38 #if defined(HAVE_SACADO_KOKKOSCORE)
39 #include "Kokkos_Core.hpp"
40 #if defined(KOKKOS_ENABLE_CUDA)
41 #include "Cuda/Kokkos_Cuda_Vectorization.hpp"
43 #if !defined(SACADO_DISABLE_CUDA_IN_KOKKOS)
44 #include "Kokkos_MemoryPool.hpp"
50 template <
typename ExecSpace>
52 ,
const size_t min_total_alloc_size
53 ,
const uint32_t min_block_alloc_size
54 ,
const uint32_t max_block_alloc_size
55 ,
const uint32_t min_superblock_size
58 template <
typename ExecSpace>
61 #if 0 && defined(HAVE_SACADO_KOKKOSCORE) && defined(KOKKOS_ENABLE_OPENMP)
63 extern const Kokkos::MemoryPool<Kokkos::OpenMP>* global_sacado_openmp_memory_pool;
68 ,
const size_t min_total_alloc_size
69 ,
const uint32_t min_block_alloc_size
70 ,
const uint32_t max_block_alloc_size
71 ,
const uint32_t min_superblock_size
74 typedef Kokkos::MemoryPool<Kokkos::OpenMP> pool_t;
75 Impl::global_sacado_openmp_memory_pool =
76 new pool_t(
typename Kokkos::OpenMP::memory_space(),
85 delete Impl::global_sacado_openmp_memory_pool;
89 #if defined(HAVE_SACADO_KOKKOSCORE) && !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(KOKKOS_ENABLE_CUDA) && defined(__CUDACC__)
93 extern const Kokkos::MemoryPool<Kokkos::Cuda>* global_sacado_cuda_memory_pool_host;
94 extern const Kokkos::MemoryPool<Kokkos::Cuda>* global_sacado_cuda_memory_pool_device;
95 #ifdef KOKKOS_ENABLE_CUDA_RELOCATABLE_DEVICE_CODE
96 extern __device__
const Kokkos::MemoryPool<Kokkos::Cuda>* global_sacado_cuda_memory_pool_on_device;
98 __device__
const Kokkos::MemoryPool<Kokkos::Cuda>* global_sacado_cuda_memory_pool_on_device = 0;
101 struct SetMemoryPoolPtr {
102 Kokkos::MemoryPool<Kokkos::Cuda>* pool_device;
103 __device__
inline void operator()(
int)
const {
104 global_sacado_cuda_memory_pool_on_device = pool_device;
114 ,
const size_t min_total_alloc_size
115 ,
const uint32_t min_block_alloc_size
116 ,
const uint32_t max_block_alloc_size
117 ,
const uint32_t min_superblock_size
120 typedef Kokkos::MemoryPool<Kokkos::Cuda> pool_t;
122 new pool_t(
typename Kokkos::Cuda::memory_space(),
123 min_total_alloc_size,
124 min_block_alloc_size,
125 max_block_alloc_size,
126 min_superblock_size);
127 Impl::SetMemoryPoolPtr
f;
128 CUDA_SAFE_CALL( cudaMalloc( &f.pool_device,
sizeof(pool_t) ) );
129 CUDA_SAFE_CALL( cudaMemcpy( f.pool_device, pool,
131 cudaMemcpyHostToDevice ) );
132 Kokkos::parallel_for(Kokkos::RangePolicy<Kokkos::Cuda>(0,1),f);
133 Impl::global_sacado_cuda_memory_pool_host = pool;
134 Impl::global_sacado_cuda_memory_pool_device = f.pool_device;
139 CUDA_SAFE_CALL( cudaFree( (
void*) Impl::global_sacado_cuda_memory_pool_device ) );
140 delete Impl::global_sacado_cuda_memory_pool_host;
145 #if !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(KOKKOS_ENABLE_CUDA) && defined(__CUDACC__)
150 __device__
inline int warpLane(
const int warp_size = 32) {
151 return ( threadIdx.x + (threadIdx.y + threadIdx.z*blockDim.y)*blockDim.x ) % warp_size;
155 template <
typename T>
156 __device__
inline T warpReduce(
T y,
const int warp_size = 32) {
157 for (
int i=1; i<warp_size; i*=2) {
158 y += Kokkos::shfl_down(y, i, warp_size);
160 y = Kokkos::shfl(y, 0, warp_size);
165 template <
typename T>
166 __device__
inline int warpScan(
T y,
const int warp_size = 32) {
167 const int lane = warpLane();
168 y = Kokkos::shfl_up(y, 1, warp_size);
171 for (
int i=1; i<warp_size; i*=2) {
172 T t = Kokkos::shfl_up(y, i, warp_size);
179 template <
typename T>
180 __device__
inline T warpBcast(
T y,
int id,
const int warp_size = 32) {
181 return Kokkos::shfl(y,
id, warp_size);
190 template <
typename T>
193 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_ENABLE_CUDA_UVM) && !defined( __CUDA_ARCH__ )
195 CUDA_SAFE_CALL( cudaMallocManaged( (
void**) &m, sz*
sizeof(
T), cudaMemAttachGlobal ) );
196 #elif defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL) && !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(__CUDA_ARCH__)
198 const int total_sz = warpReduce(sz);
199 const int lane = warpLane();
200 if (total_sz > 0 && lane == 0) {
201 m =
static_cast<T*
>(global_sacado_cuda_memory_pool_on_device->allocate(total_sz*
sizeof(
T)));
203 Kokkos::abort(
"Allocation failed. Kokkos memory pool is out of memory");
207 #elif 0 && defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL) && defined(KOKKOS_ENABLE_OPENMP)
210 if (global_sacado_openmp_memory_pool != 0) {
211 m =
static_cast<T*
>(global_sacado_openmp_memory_pool->allocate(sz*
sizeof(
T)));
213 Kokkos::abort(
"Allocation failed. Kokkos memory pool is out of memory");
216 m =
static_cast<T*
>(
operator new(sz*
sizeof(
T)));
219 T* m =
static_cast<T*
>(
operator new(sz*
sizeof(
T)));
220 #if defined(HAVE_SACADO_KOKKOSCORE)
222 Kokkos::abort(
"Allocation failed.");
228 template <
typename T>
231 #if defined( CUDA_VERSION ) && ( 6000 <= CUDA_VERSION ) && defined(KOKKOS_ENABLE_CUDA_UVM) && !defined( __CUDA_ARCH__ )
233 CUDA_SAFE_CALL( cudaFree(m) );
234 #elif defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL) && !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(__CUDA_ARCH__)
235 const int total_sz = warpReduce(sz);
236 const int lane = warpLane();
237 if (total_sz > 0 && lane == 0) {
238 global_sacado_cuda_memory_pool_on_device->deallocate((
void*) m, total_sz*
sizeof(
T));
240 #elif 0 && defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL) && defined(KOKKOS_ENABLE_OPENMP)
242 if (global_sacado_openmp_memory_pool != 0)
243 global_sacado_openmp_memory_pool->deallocate((
void*) m, sz*
sizeof(
T));
245 operator delete((
void*) m);
249 operator delete((
void*) m);
258 template <typename T, bool isScalar = IsScalarType<T>::value>
263 static T*
get(
int sz) {
265 T* m = Impl::ds_alloc<T>(sz);
267 for (
int i=0; i<sz; ++i)
278 T* m = Impl::ds_alloc<T>(sz);
280 for (
int i=0; i<sz; ++i)
294 T* m = Impl::ds_alloc<T>(sz);
296 for (
int i=0; i<sz; ++i)
297 new (p++)
T(*(src++));
310 T* m = Impl::ds_alloc<T>(sz);
312 for (
int i=0; i<sz; ++i) {
323 static void copy(
const T* src,
T* dest,
int sz) {
324 for (
int i=0; i<sz; ++i)
325 *(dest++) = *(src++);
331 T* dest,
int dest_stride,
int sz) {
332 for (
int i=0; i<sz; ++i) {
342 for (
int i=0; i<sz; ++i)
349 for (
int i=0; i<sz; ++i) {
359 for (
T* b = m; b!=e; b++)
365 #if defined(SACADO_VIEW_CUDA_HIERARCHICAL_DFAD) && !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(__CUDA_ARCH__)
369 template <
typename T>
371 static T* ds_strided_alloc(
const int sz) {
377 if (blockDim.x == 32) {
379 const int lane = threadIdx.x;
380 if (sz > 0 && lane == 0) {
381 #if defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL)
382 m =
static_cast<T*
>(global_sacado_cuda_memory_pool_on_device->allocate(sz*
sizeof(
T)));
384 Kokkos::abort(
"Allocation failed. Kokkos memory pool is out of memory");
386 m =
static_cast<T*
>(
operator new(sz*
sizeof(
T)));
387 #if defined(HAVE_SACADO_KOKKOSCORE)
389 Kokkos::abort(
"Allocation failed.");
393 m = warpBcast(m,0,blockDim.x);
397 m =
static_cast<T*
>(
operator new(sz*
sizeof(
T)));
398 #if defined(HAVE_SACADO_KOKKOSCORE)
400 Kokkos::abort(
"Allocation failed.");
408 template <
typename T>
410 static void ds_strided_free(
T* m,
int sz) {
411 if (blockDim.x == 32) {
413 const int lane = threadIdx.x;
414 if (sz > 0 && lane == 0) {
415 #if defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL)
416 global_sacado_cuda_memory_pool_on_device->deallocate((
void*) m, sz*
sizeof(
T));
418 operator delete((
void*) m);
424 operator delete((
void*) m);
435 template <
typename T>
436 struct ds_array<
T,
true> {
440 static T*
get(
int sz) {
442 T* m = Impl::ds_strided_alloc<T>(sz);
452 T* m = Impl::ds_strided_alloc<T>(sz);
453 for (
int i=threadIdx.x; i<sz; i+=blockDim.x)
467 T* m = Impl::ds_strided_alloc<T>(sz);
468 for (
int i=threadIdx.x; i<sz; i+=blockDim.x)
482 T* m = Impl::ds_strided_alloc<T>(sz);
483 for (
int i=threadIdx.x; i<sz; i+=blockDim.x)
484 m[i] = src[i*stride];
492 static void copy(
const T* src,
T* dest,
int sz) {
494 for (
int i=threadIdx.x; i<sz; i+=blockDim.x)
501 T* dest,
int dest_stride,
int sz) {
502 for (
int i=threadIdx.x; i<sz; i+=blockDim.x) {
503 dest[i*dest_stride] = src[i*src_stride];
509 static void zero(
T* dest,
int sz) {
511 for (
int i=threadIdx.x; i<sz; i+=blockDim.x)
518 for (
int i=threadIdx.x; i<sz; i+=blockDim.x) {
519 dest[i*stride] =
T(0.);
526 Impl::ds_strided_free(m, sz);
530 #elif defined(SACADO_VIEW_CUDA_HIERARCHICAL_DFAD_STRIDED) && !defined(SACADO_DISABLE_CUDA_IN_KOKKOS) && defined(__CUDA_ARCH__)
534 template <
typename T>
536 static T* ds_strided_alloc(
const int sz) {
542 if (blockDim.x == 32) {
545 const int total_sz = warpReduce(sz, blockDim.x);
546 const int lane = threadIdx.x;
547 if (total_sz > 0 && lane == 0) {
548 #if defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL)
549 m =
static_cast<T*
>(global_sacado_cuda_memory_pool_on_device->allocate(total_sz*
sizeof(
T)));
551 Kokkos::abort(
"Allocation failed. Kokkos memory pool is out of memory");
553 m =
static_cast<T*
>(
operator new(total_sz*
sizeof(
T)));
554 #if defined(HAVE_SACADO_KOKKOSCORE)
556 Kokkos::abort(
"Allocation failed.");
560 m = warpBcast(m,0,blockDim.x);
565 m =
static_cast<T*
>(
operator new(sz*
sizeof(
T)));
566 #if defined(HAVE_SACADO_KOKKOSCORE)
568 Kokkos::abort(
"Allocation failed.");
576 template <
typename T>
578 static void ds_strided_free(
T* m,
int sz) {
579 if (blockDim.x == 32) {
582 const int total_sz = warpReduce(sz, blockDim.x);
583 const int lane = threadIdx.x;
584 if (total_sz > 0 && lane == 0) {
585 #if defined(HAVE_SACADO_KOKKOSCORE) && defined(SACADO_KOKKOS_USE_MEMORY_POOL)
586 global_sacado_cuda_memory_pool_on_device->deallocate((
void*) m, total_sz*
sizeof(
T));
588 operator delete((
void*) m);
594 operator delete((
void*) m);
603 template <
typename T>
604 struct ds_array<
T,
true> {
608 static T*
get(
int sz) {
610 T* m = Impl::ds_strided_alloc<T>(sz);
620 T* m = Impl::ds_strided_alloc<T>(sz);
621 for (
int i=0; i<sz; ++i)
622 m[i*blockDim.x] = 0.0;
635 T* m = Impl::ds_strided_alloc<T>(sz);
636 for (
int i=0; i<sz; ++i)
637 m[i*blockDim.x] = src[i*blockDim.x];
650 T* m = Impl::ds_strided_alloc<T>(sz);
651 for (
int i=0; i<sz; ++i)
652 m[i*blockDim.x] = src[i*stride];
660 static void copy(
const T* src,
T* dest,
int sz) {
662 for (
int i=0; i<sz; ++i)
663 dest[i*blockDim.x] = src[i*blockDim.x];
669 T* dest,
int dest_stride,
int sz) {
670 for (
int i=0; i<sz; ++i) {
679 static void zero(
T* dest,
int sz) {
681 for (
int i=0; i<sz; ++i)
682 dest[i*blockDim.x] =
T(0.);
688 for (
int i=0; i<sz; ++i) {
697 Impl::ds_strided_free(m, sz);
707 template <
typename T>
712 static T*
get(
int sz) {
714 T* m = Impl::ds_alloc<T>(sz);
724 T* m = Impl::ds_alloc<T>(sz);
726 for (
int i=0; i<sz; ++i)
729 std::memset(m,0,sz*
sizeof(
T));
743 T* m = Impl::ds_alloc<T>(sz);
744 for (
int i=0; i<sz; ++i)
758 T* m = Impl::ds_alloc<T>(sz);
759 for (
int i=0; i<sz; ++i)
760 m[i] = src[i*stride];
768 static void copy(
const T* src,
T* dest,
int sz) {
769 if (sz > 0 && dest != NULL && src != NULL)
771 for (
int i=0; i<sz; ++i)
774 std::memcpy(dest,src,sz*
sizeof(
T));
781 T* dest,
int dest_stride,
int sz) {
782 for (
int i=0; i<sz; ++i) {
792 if (sz > 0 && dest != NULL)
794 for (
int i=0; i<sz; ++i)
797 std::memset(dest,0,sz*
sizeof(
T));
804 for (
int i=0; i<sz; ++i) {
821 #endif // SACADO_DYNAMICARRAY_HPP
static KOKKOS_INLINE_FUNCTION T * strided_get_and_fill(const T *src, int stride, int sz)
Get memory for new array of length sz and fill with entries from src.
static KOKKOS_INLINE_FUNCTION void destroy_and_release(T *m, int sz)
Destroy array elements and release memory.
static KOKKOS_INLINE_FUNCTION void copy(const T *src, T *dest, int sz)
Copy array from src to dest of length sz.
void createGlobalMemoryPool(const ExecSpace &space, const size_t min_total_alloc_size, const uint32_t min_block_alloc_size, const uint32_t max_block_alloc_size, const uint32_t min_superblock_size)
static KOKKOS_INLINE_FUNCTION void strided_zero(T *dest, int stride, int sz)
Zero out array dest of length sz.
static KOKKOS_INLINE_FUNCTION void destroy_and_release(T *m, int sz)
Destroy array elements and release memory.
static KOKKOS_INLINE_FUNCTION void strided_copy(const T *src, int src_stride, T *dest, int dest_stride, int sz)
Copy array from src to dest of length sz.
#define KOKKOS_INLINE_FUNCTION
static KOKKOS_INLINE_FUNCTION T * ds_alloc(const int sz)
static KOKKOS_INLINE_FUNCTION T * get_and_fill(int sz)
Get memory for new array of length sz and fill with zeros.
static KOKKOS_INLINE_FUNCTION void zero(T *dest, int sz)
Zero out array dest of length sz.
static KOKKOS_INLINE_FUNCTION void strided_copy(const T *src, int src_stride, T *dest, int dest_stride, int sz)
Copy array from src to dest of length sz.
static KOKKOS_INLINE_FUNCTION void copy(const T *src, T *dest, int sz)
Copy array from src to dest of length sz.
static KOKKOS_INLINE_FUNCTION T * strided_get_and_fill(const T *src, int stride, int sz)
Get memory for new array of length sz and fill with entries from src.
static KOKKOS_INLINE_FUNCTION void strided_zero(T *dest, int stride, int sz)
Zero out array dest of length sz.
static KOKKOS_INLINE_FUNCTION T * get_and_fill(const T *src, int sz)
Get memory for new array of length sz and fill with entries from src.
static KOKKOS_INLINE_FUNCTION void ds_free(T *m, int sz)
static KOKKOS_INLINE_FUNCTION T * get_and_fill(int sz)
Get memory for new array of length sz and fill with zeros.
void destroyGlobalMemoryPool(const ExecSpace &space)
static KOKKOS_INLINE_FUNCTION T * get_and_fill(const T *src, int sz)
Get memory for new array of length sz and fill with entries from src.
Dynamic array allocation class that works for any type.
static KOKKOS_INLINE_FUNCTION void zero(T *dest, int sz)
Zero out array dest of length sz.