Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:17

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // CUDA plugin include(s).
0010 #include "Acts/Plugins/Cuda/Utilities/MemoryManager.hpp"
0011 
0012 #include "ErrorCheck.cuh"
0013 
0014 // CUDA include(s).
0015 #include <cuda_runtime.h>
0016 
0017 // System include(s).
0018 #include <cmath>
0019 #include <stdexcept>
0020 
0021 namespace Acts {
0022 namespace Cuda {
0023 
0024 MemoryManager::~MemoryManager() {
0025   // Free all the allocated memory.
0026   for (DeviceMemory& mem : m_memory) {
0027     if (mem.m_ptr == nullptr) {
0028       continue;
0029     }
0030     ACTS_CUDA_ERROR_CHECK(cudaFree(mem.m_ptr));
0031   }
0032 }
0033 
0034 MemoryManager& MemoryManager::instance() {
0035   static MemoryManager mm;
0036   return mm;
0037 }
0038 
0039 void MemoryManager::setMemorySize(std::size_t sizeInBytes, int device) {
0040   // If the user didn't ask for a specific device, use the one currently used by
0041   // CUDA.
0042   if (device == -1) {
0043     ACTS_CUDA_ERROR_CHECK(cudaGetDevice(&device));
0044   }
0045 
0046   // Make sure that the internal storage variable is large enough.
0047   if (static_cast<std::size_t>(device) >= m_memory.size()) {
0048     m_memory.resize(device + 1);
0049   }
0050 
0051   // Get the object responsible for this device.
0052   DeviceMemory& mem = m_memory[device];
0053 
0054   // De-allocate any previously allocated memory.
0055   if (mem.m_ptr) {
0056     ACTS_CUDA_ERROR_CHECK(cudaFree(mem.m_ptr));
0057   }
0058 
0059   // Allocate the newly requested amount.
0060   ACTS_CUDA_ERROR_CHECK(cudaSetDevice(device));
0061   ACTS_CUDA_ERROR_CHECK(cudaMalloc(&(mem.m_ptr), sizeInBytes));
0062 
0063   // Set up the internal state of the object correctly.
0064   mem.m_size = sizeInBytes;
0065   mem.m_nextAllocation = mem.m_ptr;
0066   return;
0067 }
0068 
0069 std::size_t MemoryManager::availableMemory(int device) const {
0070   // If the user didn't ask for a specific device, use the one currently used by
0071   // CUDA.
0072   if (device == -1) {
0073     ACTS_CUDA_ERROR_CHECK(cudaGetDevice(&device));
0074   }
0075 
0076   // Make sure that memory was allocated on the requested device.
0077   if (m_memory.size() <= static_cast<std::size_t>(device)) {
0078     throw std::bad_alloc();
0079   }
0080   const DeviceMemory& mem = m_memory[device];
0081 
0082   // Return the requested information.
0083   return (mem.m_size - (mem.m_nextAllocation - mem.m_ptr));
0084 }
0085 
0086 void* MemoryManager::allocate(std::size_t sizeInBytes, int device) {
0087   // If the user didn't ask for a specific device, use the one currently used by
0088   // CUDA.
0089   if (device == -1) {
0090     ACTS_CUDA_ERROR_CHECK(cudaGetDevice(&device));
0091   }
0092 
0093   // Make sure that memory was allocated on the requested device.
0094   if (m_memory.size() <= static_cast<std::size_t>(device)) {
0095     throw std::bad_alloc();
0096   }
0097   DeviceMemory& mem = m_memory[device];
0098 
0099   // We already know what we want to return...
0100   void* result = mem.m_nextAllocation;
0101 
0102   // Make sure that all addresses given out are 8-byte aligned.
0103   static constexpr std::size_t ALIGN_SIZE = 8;
0104   const std::size_t misalignment = sizeInBytes % ALIGN_SIZE;
0105   const std::size_t padding =
0106       ((misalignment != 0) ? (ALIGN_SIZE - misalignment) : 0);
0107 
0108   // Increment the internal pointer.
0109   mem.m_nextAllocation += sizeInBytes + padding;
0110   // And make sure that we didn't run out of memory.
0111   if (mem.m_nextAllocation - mem.m_ptr >= mem.m_size) {
0112     throw std::bad_alloc();
0113   }
0114 
0115   // Apparently everything is okay.
0116   return result;
0117 }
0118 
0119 void MemoryManager::reset(int device) {
0120   // If the user didn't ask for a specific device, use the one currently used by
0121   // CUDA.
0122   if (device == -1) {
0123     ACTS_CUDA_ERROR_CHECK(cudaGetDevice(&device));
0124   }
0125 
0126   // Make sure that memory was allocated on the requested device.
0127   if (m_memory.size() <= static_cast<std::size_t>(device)) {
0128     throw std::bad_alloc();
0129   }
0130   DeviceMemory& mem = m_memory[device];
0131 
0132   // Note down how much memory was used in total until the reset.
0133   mem.m_maxUsage = std::max(mem.m_maxUsage, mem.m_nextAllocation - mem.m_ptr);
0134   // Return the internal pointer to its startout location.
0135   mem.m_nextAllocation = mem.m_ptr;
0136   return;
0137 }
0138 
0139 MemoryManager::MemoryManager() {
0140   // Allocate 1500 MBs of memory as a start on the default device.
0141   setMemorySize(1500 * 1024l * 1024l);
0142 }
0143 
0144 }  // namespace Cuda
0145 }  // namespace Acts