Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:47

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2023-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file corecel/data/PinnedAllocator.t.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include "PinnedAllocator.hh"
0011 
0012 #include <limits>
0013 #include <new>
0014 
0015 #include "corecel/DeviceRuntimeApi.hh"
0016 
0017 #include "corecel/Assert.hh"
0018 #include "corecel/Macros.hh"
0019 #include "corecel/io/Logger.hh"
0020 #include "corecel/sys/Device.hh"
0021 
0022 namespace celeritas
0023 {
0024 //---------------------------------------------------------------------------//
0025 /*!
0026  * Allocate and construct space for \c n objects.
0027  *
0028  * If any devices are available, use pinned memory. Otherwise, use standard
0029  * allocation.
0030  */
0031 template<class T>
0032 T* PinnedAllocator<T>::allocate(std::size_t n)
0033 {
0034     CELER_EXPECT(n != 0);
0035     if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
0036         throw std::bad_array_new_length();
0037 
0038     void* p{nullptr};
0039     if (Device::num_devices() > 0)
0040     {
0041         // CUDA and HIP currently have a different API to allocate pinned host
0042         // memory
0043 #if CELERITAS_USE_CUDA
0044         CELER_CUDA_CALL(cudaHostAlloc(
0045             &p, n * sizeof(T), CELER_DEVICE_PREFIX(HostAllocDefault)));
0046 #elif CELERITAS_USE_HIP
0047         CELER_HIP_CALL(hipHostMalloc(
0048             &p, n * sizeof(T), CELER_DEVICE_PREFIX(HostMallocDefault)));
0049 #endif
0050     }
0051     else
0052     {
0053         p = ::operator new(n * sizeof(T));
0054     }
0055 
0056     if (!p)
0057     {
0058         throw std::bad_alloc();
0059     }
0060 
0061     return static_cast<T*>(p);
0062 }
0063 
0064 //---------------------------------------------------------------------------//
0065 /*!
0066  * Free allocated memory.
0067  *
0068  * Because \c Device::num_devices is static, this will always be symmetric
0069  * with the \c PinnedAllocator::allocate call.
0070  */
0071 template<class T>
0072 void PinnedAllocator<T>::deallocate(T* p, std::size_t) noexcept
0073 {
0074     if (Device::num_devices() > 0)
0075     {
0076         try
0077         {
0078             // NOTE that Free/Host switch places in the two languages
0079 #if CELERITAS_USE_CUDA
0080             CELER_CUDA_CALL(cudaFreeHost(p));
0081 #elif CELERITAS_USE_HIP
0082             CELER_HIP_CALL(hipHostFree(p));
0083 #endif
0084         }
0085         catch (RuntimeError const& e)
0086         {
0087             CELER_LOG(debug)
0088                 << "While freeing pinned host memory: " << e.what();
0089         }
0090     }
0091     else
0092     {
0093         ::operator delete(p);
0094     }
0095 }
0096 
0097 //---------------------------------------------------------------------------//
0098 }  // namespace celeritas