19# include <cuda_runtime.h>
23#include <boost/fiber/condition_variable.hpp>
24#include <boost/fiber/mutex.hpp>
33 using namespace std::chrono_literals;
35 const std::string DEVARREXC =
"CUDADeviceArrayException";
36 std::string err_fmt( cudaError_t err, std::string file,
int line ) {
37 const char* errname = cudaGetErrorName( err );
38 const char* errstr = cudaGetErrorString( err );
40 std::format(
"Encountered CUDA error {} [{}]: {} on {}:{}", errname,
int( err ), errstr, file, line );
44 boost::fibers::mutex gpu_mem_mtx;
45 boost::fibers::condition_variable gpu_mem_cv;
50 void* devPtr =
nullptr;
51 cudaError_t err = cudaSuccess;
52 auto start_time = std::chrono::steady_clock::now();
54 err = cudaMallocAsync( &devPtr, size, stream );
55 if ( err == cudaSuccess ) {
break; }
56 if ( err == cudaErrorMemoryAllocation && parent !=
nullptr ) {
59 std::unique_lock lck( gpu_mem_mtx );
60 gpu_mem_cv.wait( lck );
64 }
while ( err == cudaErrorMemoryAllocation );
71 void* devPtr =
nullptr;
72 cudaError_t err = cudaSuccess;
73 auto start_time = std::chrono::steady_clock::now();
75 err = cudaMalloc( &devPtr, size );
76 if ( err == cudaSuccess ) {
break; }
77 if ( err == cudaErrorMemoryAllocation ) {
81 if ( parent !=
nullptr ) {
82 std::unique_lock lck( gpu_mem_mtx );
83 gpu_mem_cv.wait( lck );
86 std::this_thread::sleep_for( 100ms );
91 }
while ( err == cudaErrorMemoryAllocation );
96 cudaError_t err = cudaFreeAsync( ptr, stream );
97 if ( err != cudaSuccess ) {
100 gpu_mem_cv.notify_all();
104 cudaError_t err = cudaFree( ptr );
105 if ( err != cudaSuccess ) {
108 gpu_mem_cv.notify_all();
112 cudaError_t err = cudaMemcpyAsync( devPtr, hstPtr, size, cudaMemcpyHostToDevice, stream );
113 if ( err != cudaSuccess ) {
117 stream.await().orThrow(
"Await error", DEVARREXC );
121 cudaError_t err = cudaMemcpy( devPtr, hstPtr, size, cudaMemcpyHostToDevice );
122 if ( err != cudaSuccess ) {
128 cudaError_t err = cudaMemcpyAsync( hstPtr, devPtr, size, cudaMemcpyDeviceToHost, stream );
129 if ( err != cudaSuccess ) {
133 stream.await().orThrow(
"Await error", DEVARREXC );
137 cudaError_t err = cudaMemcpy( hstPtr, devPtr, size, cudaMemcpyDeviceToHost );
138 if ( err != cudaSuccess ) {
144 cudaError_t err = cudaMemcpyAsync( destDevPtr, srcDevPtr, size, cudaMemcpyDeviceToDevice, stream );
145 if ( err != cudaSuccess ) {
151 cudaError_t err = cudaMemcpy( destDevPtr, srcDevPtr, size, cudaMemcpyDeviceToDevice );
152 if ( err != cudaSuccess ) {
Base class for asynchronous algorithms.
virtual StatusCode restoreAfterSuspend() const
Restore after suspend.
Define general base for Gaudi exception.
const StatusCode & orThrow(std::string_view message, std::string_view tag) const
Throw a GaudiException in case of failures.
constexpr static const auto FAILURE
void copyDeviceToDeviceNoStream(void *destDevPtr, const void *srcDevPtr, std::size_t size)
void * allocateNoStream(std::size_t size, Gaudi::AsynchronousAlgorithm *parent)
void copyDeviceToHostWithStream(void *hstPtr, const void *devPtr, std::size_t size, Stream &stream)
void copyHostToDeviceNoStream(void *devPtr, const void *hstPtr, std::size_t size)
void * allocateWithStream(std::size_t size, Stream &stream)
void copyDeviceToHostNoStream(void *hstPtr, const void *devPtr, std::size_t size)
void copyDeviceToDeviceWithStream(void *destDevPtr, const void *srcDevPtr, std::size_t size, Stream &stream)
void freeNoStream(void *ptr)
void copyHostToDeviceWithStream(void *devPtr, const void *hstPtr, std::size_t size, Stream &stream)
void freeWithStream(void *ptr, Stream &stream)