xref: /petsc/src/sys/objects/device/impls/cupm/cupmallocator.hpp (revision 96a4b4d95ea58ea02aff154c6b83fc6968de23ca)
10e6b6b59SJacob Faibussowitsch #ifndef CUPMALLOCATOR_HPP
20e6b6b59SJacob Faibussowitsch #define CUPMALLOCATOR_HPP
30e6b6b59SJacob Faibussowitsch 
40e6b6b59SJacob Faibussowitsch #if defined(__cplusplus)
50e6b6b59SJacob Faibussowitsch   #include <petsc/private/cpp/object_pool.hpp>
60e6b6b59SJacob Faibussowitsch 
70e6b6b59SJacob Faibussowitsch   #include "../segmentedmempool.hpp"
80e6b6b59SJacob Faibussowitsch   #include "cupmthrustutility.hpp"
90e6b6b59SJacob Faibussowitsch 
10f3146f24SJacob Faibussowitsch   #include <thrust/device_ptr.h>
11f3146f24SJacob Faibussowitsch   #include <thrust/fill.h>
12f3146f24SJacob Faibussowitsch 
130e6b6b59SJacob Faibussowitsch   #include <limits> // std::numeric_limits
140e6b6b59SJacob Faibussowitsch 
15d71ae5a4SJacob Faibussowitsch namespace Petsc
16d71ae5a4SJacob Faibussowitsch {
170e6b6b59SJacob Faibussowitsch 
18d71ae5a4SJacob Faibussowitsch namespace device
19d71ae5a4SJacob Faibussowitsch {
200e6b6b59SJacob Faibussowitsch 
21d71ae5a4SJacob Faibussowitsch namespace cupm
22d71ae5a4SJacob Faibussowitsch {
230e6b6b59SJacob Faibussowitsch 
240e6b6b59SJacob Faibussowitsch // ==========================================================================================
250e6b6b59SJacob Faibussowitsch // CUPM Host Allocator
260e6b6b59SJacob Faibussowitsch // ==========================================================================================
270e6b6b59SJacob Faibussowitsch 
280e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType = char>
290e6b6b59SJacob Faibussowitsch class HostAllocator;
300e6b6b59SJacob Faibussowitsch 
310e6b6b59SJacob Faibussowitsch // Allocator class to allocate pinned host memory for use with device
320e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType>
330e6b6b59SJacob Faibussowitsch class HostAllocator : public memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>, impl::Interface<T> {
340e6b6b59SJacob Faibussowitsch public:
35*96a4b4d9SJacob Faibussowitsch   PETSC_CUPM_INHERIT_INTERFACE_TYPEDEFS_USING(T);
360e6b6b59SJacob Faibussowitsch   using base_type       = memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>;
37ff8f30bbSJacob Faibussowitsch   using real_value_type = typename base_type::real_value_type;
38ff8f30bbSJacob Faibussowitsch   using size_type       = typename base_type::size_type;
39ff8f30bbSJacob Faibussowitsch   using value_type      = typename base_type::value_type;
400e6b6b59SJacob Faibussowitsch 
410e6b6b59SJacob Faibussowitsch   template <typename U>
42089fb57cSJacob Faibussowitsch   static PetscErrorCode allocate(value_type **, size_type, const StreamBase<U> *) noexcept;
430e6b6b59SJacob Faibussowitsch   template <typename U>
44089fb57cSJacob Faibussowitsch   static PetscErrorCode deallocate(value_type *, const StreamBase<U> *) noexcept;
450e6b6b59SJacob Faibussowitsch   template <typename U>
46089fb57cSJacob Faibussowitsch   static PetscErrorCode uninitialized_copy(value_type *, const value_type *, size_type, const StreamBase<U> *) noexcept;
470e6b6b59SJacob Faibussowitsch };
480e6b6b59SJacob Faibussowitsch 
490e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
500e6b6b59SJacob Faibussowitsch template <typename U>
51d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::allocate(value_type **ptr, size_type n, const StreamBase<U> *) noexcept
52d71ae5a4SJacob Faibussowitsch {
530e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
540e6b6b59SJacob Faibussowitsch   PetscCall(PetscCUPMMallocHost(ptr, n));
553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
560e6b6b59SJacob Faibussowitsch }
570e6b6b59SJacob Faibussowitsch 
580e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
590e6b6b59SJacob Faibussowitsch template <typename U>
60d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::deallocate(value_type *ptr, const StreamBase<U> *) noexcept
61d71ae5a4SJacob Faibussowitsch {
620e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
630e6b6b59SJacob Faibussowitsch   PetscCallCUPM(cupmFreeHost(ptr));
643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
650e6b6b59SJacob Faibussowitsch }
660e6b6b59SJacob Faibussowitsch 
670e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
680e6b6b59SJacob Faibussowitsch template <typename U>
69d71ae5a4SJacob Faibussowitsch inline PetscErrorCode HostAllocator<T, P>::uninitialized_copy(value_type *dest, const value_type *src, size_type n, const StreamBase<U> *stream) noexcept
70d71ae5a4SJacob Faibussowitsch {
710e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
720e6b6b59SJacob Faibussowitsch   PetscCall(PetscCUPMMemcpyAsync(dest, src, n, cupmMemcpyHostToHost, stream->get_stream(), true));
733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
740e6b6b59SJacob Faibussowitsch }
750e6b6b59SJacob Faibussowitsch 
760e6b6b59SJacob Faibussowitsch // ==========================================================================================
770e6b6b59SJacob Faibussowitsch // CUPM Device Allocator
780e6b6b59SJacob Faibussowitsch // ==========================================================================================
790e6b6b59SJacob Faibussowitsch 
800e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType = char>
810e6b6b59SJacob Faibussowitsch class DeviceAllocator;
820e6b6b59SJacob Faibussowitsch 
830e6b6b59SJacob Faibussowitsch template <DeviceType T, typename PetscType>
840e6b6b59SJacob Faibussowitsch class DeviceAllocator : public memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>, impl::Interface<T> {
850e6b6b59SJacob Faibussowitsch public:
86*96a4b4d9SJacob Faibussowitsch   PETSC_CUPM_INHERIT_INTERFACE_TYPEDEFS_USING(T);
870e6b6b59SJacob Faibussowitsch   using base_type       = memory::impl::SegmentedMemoryPoolAllocatorBase<PetscType>;
88ff8f30bbSJacob Faibussowitsch   using real_value_type = typename base_type::real_value_type;
89ff8f30bbSJacob Faibussowitsch   using size_type       = typename base_type::size_type;
90ff8f30bbSJacob Faibussowitsch   using value_type      = typename base_type::value_type;
910e6b6b59SJacob Faibussowitsch 
920e6b6b59SJacob Faibussowitsch   template <typename U>
93089fb57cSJacob Faibussowitsch   static PetscErrorCode allocate(value_type **, size_type, const StreamBase<U> *) noexcept;
940e6b6b59SJacob Faibussowitsch   template <typename U>
95089fb57cSJacob Faibussowitsch   static PetscErrorCode deallocate(value_type *, const StreamBase<U> *) noexcept;
960e6b6b59SJacob Faibussowitsch   template <typename U>
97089fb57cSJacob Faibussowitsch   static PetscErrorCode zero(value_type *, size_type, const StreamBase<U> *) noexcept;
980e6b6b59SJacob Faibussowitsch   template <typename U>
99089fb57cSJacob Faibussowitsch   static PetscErrorCode uninitialized_copy(value_type *, const value_type *, size_type, const StreamBase<U> *) noexcept;
1000e6b6b59SJacob Faibussowitsch   template <typename U>
101089fb57cSJacob Faibussowitsch   static PetscErrorCode set_canary(value_type *, size_type, const StreamBase<U> *) noexcept;
1020e6b6b59SJacob Faibussowitsch };
1030e6b6b59SJacob Faibussowitsch 
1040e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1050e6b6b59SJacob Faibussowitsch template <typename U>
106d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::allocate(value_type **ptr, size_type n, const StreamBase<U> *stream) noexcept
107d71ae5a4SJacob Faibussowitsch {
1080e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1090e6b6b59SJacob Faibussowitsch   PetscCall(PetscCUPMMallocAsync(ptr, n, stream->get_stream()));
1103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1110e6b6b59SJacob Faibussowitsch }
1120e6b6b59SJacob Faibussowitsch 
1130e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1140e6b6b59SJacob Faibussowitsch template <typename U>
115d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::deallocate(value_type *ptr, const StreamBase<U> *stream) noexcept
116d71ae5a4SJacob Faibussowitsch {
1170e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1180e6b6b59SJacob Faibussowitsch   PetscCallCUPM(cupmFreeAsync(ptr, stream->get_stream()));
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1200e6b6b59SJacob Faibussowitsch }
1210e6b6b59SJacob Faibussowitsch 
1220e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1230e6b6b59SJacob Faibussowitsch template <typename U>
124d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::zero(value_type *ptr, size_type n, const StreamBase<U> *stream) noexcept
125d71ae5a4SJacob Faibussowitsch {
1260e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1270e6b6b59SJacob Faibussowitsch   PetscCall(PetscCUPMMemsetAsync(ptr, 0, n, stream->get_stream(), true));
1283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1290e6b6b59SJacob Faibussowitsch }
1300e6b6b59SJacob Faibussowitsch 
1310e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1320e6b6b59SJacob Faibussowitsch template <typename U>
133d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::uninitialized_copy(value_type *dest, const value_type *src, size_type n, const StreamBase<U> *stream) noexcept
134d71ae5a4SJacob Faibussowitsch {
1350e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
1360e6b6b59SJacob Faibussowitsch   PetscCall(PetscCUPMMemcpyAsync(dest, src, n, cupmMemcpyDeviceToDevice, stream->get_stream(), true));
1373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1380e6b6b59SJacob Faibussowitsch }
1390e6b6b59SJacob Faibussowitsch 
1400e6b6b59SJacob Faibussowitsch template <DeviceType T, typename P>
1410e6b6b59SJacob Faibussowitsch template <typename U>
142d71ae5a4SJacob Faibussowitsch inline PetscErrorCode DeviceAllocator<T, P>::set_canary(value_type *ptr, size_type n, const StreamBase<U> *stream) noexcept
143d71ae5a4SJacob Faibussowitsch {
1440e6b6b59SJacob Faibussowitsch   using limit_t           = std::numeric_limits<real_value_type>;
1450e6b6b59SJacob Faibussowitsch   const value_type canary = limit_t::has_signaling_NaN ? limit_t::signaling_NaN() : limit_t::max();
146f3146f24SJacob Faibussowitsch   const auto       xptr   = thrust::device_pointer_cast(ptr);
1470e6b6b59SJacob Faibussowitsch 
1480e6b6b59SJacob Faibussowitsch   PetscFunctionBegin;
149f3146f24SJacob Faibussowitsch   PetscCallThrust(THRUST_CALL(thrust::fill, stream->get_stream(), xptr, xptr + n, canary));
1503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1510e6b6b59SJacob Faibussowitsch }
1520e6b6b59SJacob Faibussowitsch 
1530e6b6b59SJacob Faibussowitsch } // namespace cupm
1540e6b6b59SJacob Faibussowitsch 
1550e6b6b59SJacob Faibussowitsch } // namespace device
1560e6b6b59SJacob Faibussowitsch 
1570e6b6b59SJacob Faibussowitsch } // namespace Petsc
1580e6b6b59SJacob Faibussowitsch 
1590e6b6b59SJacob Faibussowitsch #endif // __cplusplus
1600e6b6b59SJacob Faibussowitsch 
1610e6b6b59SJacob Faibussowitsch #endif // CUPMALLOCATOR_HPP
162