1a4963045SJacob Faibussowitsch #pragma once
20e6b6b59SJacob Faibussowitsch
30e6b6b59SJacob Faibussowitsch #include <petsc/private/cpp/object_pool.hpp>
40e6b6b59SJacob Faibussowitsch
50e6b6b59SJacob Faibussowitsch #include "../segmentedmempool.hpp"
60e6b6b59SJacob Faibussowitsch #include "cupmthrustutility.hpp"
70e6b6b59SJacob Faibussowitsch
8f3146f24SJacob Faibussowitsch #include <thrust/device_ptr.h>
9f3146f24SJacob Faibussowitsch #include <thrust/fill.h>
10f3146f24SJacob Faibussowitsch
110e6b6b59SJacob Faibussowitsch #include <limits> // std::numeric_limits
120e6b6b59SJacob Faibussowitsch
13d71ae5a4SJacob Faibussowitsch namespace Petsc
14d71ae5a4SJacob Faibussowitsch {
150e6b6b59SJacob Faibussowitsch
16d71ae5a4SJacob Faibussowitsch namespace device
17d71ae5a4SJacob Faibussowitsch {
180e6b6b59SJacob Faibussowitsch
19d71ae5a4SJacob Faibussowitsch namespace cupm
20d71ae5a4SJacob Faibussowitsch {
210e6b6b59SJacob Faibussowitsch
220e6b6b59SJacob Faibussowitsch // ==========================================================================================
230e6b6b59SJacob Faibussowitsch // CUPM Host Allocator
240e6b6b59SJacob Faibussowitsch // ==========================================================================================
250e6b6b59SJacob Faibussowitsch
260e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType = char>
270e6b6b59SJacob Faibussowitsch class HostAllocator;
280e6b6b59SJacob Faibussowitsch
290e6b6b59SJacob Faibussowitsch // Allocator class to allocate pinned host memory for use with device
300e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType>
31*85f25e71SJed Brown class PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL HostAllocator : public memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>, impl::Interface<T> {
320e6b6b59SJacob Faibussowitsch public:
3396a4b4d9SJacob Faibussowitsch PETSC_CUPM_INHERIT_INTERFACE_TYPEDEFS_USING(T);
340e6b6b59SJacob Faibussowitsch using base_type = memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>;
35ff8f30bbSJacob Faibussowitsch using real_value_type = typename base_type::real_value_type;
36ff8f30bbSJacob Faibussowitsch using size_type = typename base_type::size_type;
37ff8f30bbSJacob Faibussowitsch using value_type = typename base_type::value_type;
380e6b6b59SJacob Faibussowitsch
390e6b6b59SJacob Faibussowitsch template <typename U>
40089fb57cSJacob Faibussowitsch static PetscErrorCode allocate(value_type **, size_type, const StreamBase<U> *) noexcept;
410e6b6b59SJacob Faibussowitsch template <typename U>
42089fb57cSJacob Faibussowitsch static PetscErrorCode deallocate(value_type *, const StreamBase<U> *) noexcept;
430e6b6b59SJacob Faibussowitsch template <typename U>
44089fb57cSJacob Faibussowitsch static PetscErrorCode uninitialized_copy(value_type *, const value_type *, size_type, const StreamBase<U> *) noexcept;
450e6b6b59SJacob Faibussowitsch };
460e6b6b59SJacob Faibussowitsch
470e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
480e6b6b59SJacob Faibussowitsch template <typename U>
allocate(value_type ** ptr,size_type n,const StreamBase<U> *)49d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::allocate(value_type **ptr, size_type n, const StreamBase<U> *) noexcept
50d71ae5a4SJacob Faibussowitsch {
510e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
520e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMMallocHost(ptr, n));
533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
540e6b6b59SJacob Faibussowitsch }
550e6b6b59SJacob Faibussowitsch
560e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
570e6b6b59SJacob Faibussowitsch template <typename U>
deallocate(value_type * ptr,const StreamBase<U> *)58d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::deallocate(value_type *ptr, const StreamBase<U> *) noexcept
59d71ae5a4SJacob Faibussowitsch {
600e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
610e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmFreeHost(ptr));
623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
630e6b6b59SJacob Faibussowitsch }
640e6b6b59SJacob Faibussowitsch
650e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
660e6b6b59SJacob Faibussowitsch template <typename U>
uninitialized_copy(value_type * dest,const value_type * src,size_type n,const StreamBase<U> * stream)67d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::uninitialized_copy(value_type *dest, const value_type *src, size_type n, const StreamBase<U> *stream) noexcept
68d71ae5a4SJacob Faibussowitsch {
690e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
700e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMMemcpyAsync(dest, src, n, cupmMemcpyHostToHost, stream->get_stream(), true));
713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
720e6b6b59SJacob Faibussowitsch }
730e6b6b59SJacob Faibussowitsch
740e6b6b59SJacob Faibussowitsch // ==========================================================================================
750e6b6b59SJacob Faibussowitsch // CUPM Device Allocator
760e6b6b59SJacob Faibussowitsch // ==========================================================================================
770e6b6b59SJacob Faibussowitsch
780e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType = char>
790e6b6b59SJacob Faibussowitsch class DeviceAllocator;
800e6b6b59SJacob Faibussowitsch
810e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType>
82*85f25e71SJed Brown class PETSC_SINGLE_LIBRARY_VISIBILITY_INTERNAL DeviceAllocator : public memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>, impl::Interface<T> {
830e6b6b59SJacob Faibussowitsch public:
8496a4b4d9SJacob Faibussowitsch PETSC_CUPM_INHERIT_INTERFACE_TYPEDEFS_USING(T);
850e6b6b59SJacob Faibussowitsch using base_type = memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>;
86ff8f30bbSJacob Faibussowitsch using real_value_type = typename base_type::real_value_type;
87ff8f30bbSJacob Faibussowitsch using size_type = typename base_type::size_type;
88ff8f30bbSJacob Faibussowitsch using value_type = typename base_type::value_type;
890e6b6b59SJacob Faibussowitsch
900e6b6b59SJacob Faibussowitsch template <typename U>
91089fb57cSJacob Faibussowitsch static PetscErrorCode allocate(value_type **, size_type, const StreamBase<U> *) noexcept;
920e6b6b59SJacob Faibussowitsch template <typename U>
93089fb57cSJacob Faibussowitsch static PetscErrorCode deallocate(value_type *, const StreamBase<U> *) noexcept;
940e6b6b59SJacob Faibussowitsch template <typename U>
95089fb57cSJacob Faibussowitsch static PetscErrorCode zero(value_type *, size_type, const StreamBase<U> *) noexcept;
960e6b6b59SJacob Faibussowitsch template <typename U>
97089fb57cSJacob Faibussowitsch static PetscErrorCode uninitialized_copy(value_type *, const value_type *, size_type, const StreamBase<U> *) noexcept;
980e6b6b59SJacob Faibussowitsch template <typename U>
99089fb57cSJacob Faibussowitsch static PetscErrorCode set_canary(value_type *, size_type, const StreamBase<U> *) noexcept;
1000e6b6b59SJacob Faibussowitsch };
1010e6b6b59SJacob Faibussowitsch
1020e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1030e6b6b59SJacob Faibussowitsch template <typename U>
allocate(value_type ** ptr,size_type n,const StreamBase<U> * stream)104d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::allocate(value_type **ptr, size_type n, const StreamBase<U> *stream) noexcept
105d71ae5a4SJacob Faibussowitsch {
1060e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1070e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMMallocAsync(ptr, n, stream->get_stream()));
1083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1090e6b6b59SJacob Faibussowitsch }
1100e6b6b59SJacob Faibussowitsch
1110e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1120e6b6b59SJacob Faibussowitsch template <typename U>
deallocate(value_type * ptr,const StreamBase<U> * stream)113d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::deallocate(value_type *ptr, const StreamBase<U> *stream) noexcept
114d71ae5a4SJacob Faibussowitsch {
1150e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1160e6b6b59SJacob Faibussowitsch PetscCallCUPM(cupmFreeAsync(ptr, stream->get_stream()));
1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1180e6b6b59SJacob Faibussowitsch }
1190e6b6b59SJacob Faibussowitsch
1200e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1210e6b6b59SJacob Faibussowitsch template <typename U>
zero(value_type * ptr,size_type n,const StreamBase<U> * stream)122d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::zero(value_type *ptr, size_type n, const StreamBase<U> *stream) noexcept
123d71ae5a4SJacob Faibussowitsch {
1240e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1250e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMMemsetAsync(ptr, 0, n, stream->get_stream(), true));
1263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1270e6b6b59SJacob Faibussowitsch }
1280e6b6b59SJacob Faibussowitsch
1290e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1300e6b6b59SJacob Faibussowitsch template <typename U>
uninitialized_copy(value_type * dest,const value_type * src,size_type n,const StreamBase<U> * stream)131d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::uninitialized_copy(value_type *dest, const value_type *src, size_type n, const StreamBase<U> *stream) noexcept
132d71ae5a4SJacob Faibussowitsch {
1330e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
1340e6b6b59SJacob Faibussowitsch PetscCall(PetscCUPMMemcpyAsync(dest, src, n, cupmMemcpyDeviceToDevice, stream->get_stream(), true));
1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1360e6b6b59SJacob Faibussowitsch }
1370e6b6b59SJacob Faibussowitsch
1380e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1390e6b6b59SJacob Faibussowitsch template <typename U>
set_canary(value_type * ptr,size_type n,const StreamBase<U> * stream)140d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::set_canary(value_type *ptr, size_type n, const StreamBase<U> *stream) noexcept
141d71ae5a4SJacob Faibussowitsch {
1420e6b6b59SJacob Faibussowitsch using limit_t = std::numeric_limits<real_value_type>;
1430e6b6b59SJacob Faibussowitsch const value_type canary = limit_t::has_signaling_NaN ? limit_t::signaling_NaN() : limit_t::max();
144f3146f24SJacob Faibussowitsch const auto xptr = thrust::device_pointer_cast(ptr);
1450e6b6b59SJacob Faibussowitsch
1460e6b6b59SJacob Faibussowitsch PetscFunctionBegin;
147f3146f24SJacob Faibussowitsch PetscCallThrust(THRUST_CALL(thrust::fill, stream->get_stream(), xptr, xptr + n, canary));
1483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1490e6b6b59SJacob Faibussowitsch }
1500e6b6b59SJacob Faibussowitsch
1510e6b6b59SJacob Faibussowitsch } // namespace cupm
1520e6b6b59SJacob Faibussowitsch
1530e6b6b59SJacob Faibussowitsch } // namespace device
1540e6b6b59SJacob Faibussowitsch
1550e6b6b59SJacob Faibussowitsch } // namespace Petsc
156