// Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced // at the Lawrence Livermore National Laboratory. All Rights reserved. See files // LICENSE and NOTICE for details. LLNL-CODE-806117. // // This file is part of the MFEM library. For more information and source code // availability visit https://mfem.org. // // MFEM is free software; you can redistribute it and/or modify it under the // terms of the BSD-3 license. We welcome feedback and contributions, see file // CONTRIBUTING.md for details. #include "backends.hpp" #include "globals.hpp" namespace mfem { // Internal debug option, useful for tracking CUDA allocations, deallocations // and transfers. // #define MFEM_TRACK_CUDA_MEM #ifdef MFEM_USE_CUDA void mfem_cuda_error(cudaError_t err, const char *expr, const char *func, const char *file, int line) { mfem::err << "\n\nCUDA error: (" << expr << ") failed with error:\n --> " << cudaGetErrorString(err) << "\n ... in function: " << func << "\n ... in file: " << file << ':' << line << '\n'; mfem_error(); } #endif void* CuMemAlloc(void** dptr, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemAlloc(): allocating " << bytes << " bytes ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMalloc(dptr, bytes)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done: " << *dptr << std::endl; #endif #endif return *dptr; } void* CuMallocManaged(void** dptr, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMallocManaged(): allocating " << bytes << " bytes ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMallocManaged(dptr, bytes)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done: " << *dptr << std::endl; #endif #endif return *dptr; } void* CuMemAllocHostPinned(void** ptr, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemAllocHostPinned(): allocating " << bytes << " bytes ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMallocHost(ptr, bytes)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done: " << *ptr << std::endl; #endif #endif return *ptr; } void* CuMemFree(void *dptr) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemFree(): deallocating memory @ " << dptr << " ... " << std::flush; #endif MFEM_GPU_CHECK(cudaFree(dptr)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done." << std::endl; #endif #endif return dptr; } void* CuMemFreeHostPinned(void *ptr) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemFreeHostPinned(): deallocating memory @ " << ptr << " ... " << std::flush; #endif MFEM_GPU_CHECK(cudaFreeHost(ptr)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done." << std::endl; #endif #endif return ptr; } void* CuMemcpyHtoD(void* dst, const void* src, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemcpyHtoD(): copying " << bytes << " bytes from " << src << " to " << dst << " ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMemcpy(dst, src, bytes, cudaMemcpyHostToDevice)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done." << std::endl; #endif #endif return dst; } void* CuMemcpyHtoDAsync(void* dst, const void* src, size_t bytes) { #ifdef MFEM_USE_CUDA MFEM_GPU_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyHostToDevice)); #endif return dst; } void* CuMemcpyDtoD(void *dst, const void *src, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemcpyDtoD(): copying " << bytes << " bytes from " << src << " to " << dst << " ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMemcpy(dst, src, bytes, cudaMemcpyDeviceToDevice)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done." << std::endl; #endif #endif return dst; } void* CuMemcpyDtoDAsync(void* dst, const void *src, size_t bytes) { #ifdef MFEM_USE_CUDA MFEM_GPU_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyDeviceToDevice)); #endif return dst; } void* CuMemcpyDtoH(void *dst, const void *src, size_t bytes) { #ifdef MFEM_USE_CUDA #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "CuMemcpyDtoH(): copying " << bytes << " bytes from " << src << " to " << dst << " ... " << std::flush; #endif MFEM_GPU_CHECK(cudaMemcpy(dst, src, bytes, cudaMemcpyDeviceToHost)); #ifdef MFEM_TRACK_CUDA_MEM mfem::out << "done." << std::endl; #endif #endif return dst; } void* CuMemcpyDtoHAsync(void *dst, const void *src, size_t bytes) { #ifdef MFEM_USE_CUDA MFEM_GPU_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyDeviceToHost)); #endif return dst; } void CuCheckLastError() { #ifdef MFEM_USE_CUDA MFEM_GPU_CHECK(cudaGetLastError()); #endif } int CuGetDeviceCount() { int num_gpus = -1; #ifdef MFEM_USE_CUDA MFEM_GPU_CHECK(cudaGetDeviceCount(&num_gpus)); #endif return num_gpus; } } // namespace mfem