mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5951 from kjetilly/cuda_resources
Added utility class to hold a GPU resource (stream, event, graph, etc).
This commit is contained in:
commit
2babeb848d
@ -728,6 +728,7 @@ if(CUDA_FOUND)
|
||||
gpu_ad
|
||||
gpu_linear_two_phase_material
|
||||
gpuPvt
|
||||
gpu_resources
|
||||
smart_pointers
|
||||
PROPERTIES LABELS ${gpu_label})
|
||||
endif()
|
||||
|
@ -313,7 +313,6 @@ if (HAVE_CUDA)
|
||||
ADD_CUDA_OR_HIP_FILE(PUBLIC_HEADER_FILES opm/simulators/linalg GpuBlockPreconditioner.hpp)
|
||||
ADD_CUDA_OR_HIP_FILE(PUBLIC_HEADER_FILES opm/simulators/linalg PreconditionerHolder.hpp)
|
||||
ADD_CUDA_OR_HIP_FILE(PUBLIC_HEADER_FILES opm/simulators/linalg set_device.hpp)
|
||||
ADD_CUDA_OR_HIP_FILE(PUBLIC_HEADER_FILES opm/simulators/linalg gpu_smart_pointer.hpp)
|
||||
endif()
|
||||
|
||||
if(USE_GPU_BRIDGE)
|
||||
@ -470,7 +469,7 @@ if (HAVE_CUDA)
|
||||
ADD_CUDA_OR_HIP_FILE(TEST_SOURCE_FILES tests test_gpu_linear_two_phase_material.cu)
|
||||
ADD_CUDA_OR_HIP_FILE(TEST_SOURCE_FILES tests test_gpuPvt.cu)
|
||||
ADD_CUDA_OR_HIP_FILE(TEST_SOURCE_FILES tests test_smart_pointers.cu)
|
||||
|
||||
ADD_CUDA_OR_HIP_FILE(TEST_SOURCE_FILES tests test_gpu_resources.cu)
|
||||
|
||||
# for loop providing the flag --expt-relaxed-constexpr to fix some cuda issues with constexpr
|
||||
if(NOT CONVERT_CUDA_TO_HIP)
|
||||
@ -988,8 +987,6 @@ list (APPEND PUBLIC_HEADER_FILES
|
||||
opm/simulators/wells/BlackoilWellModelGasLift_impl.hpp
|
||||
opm/simulators/wells/BlackoilWellModelGeneric.hpp
|
||||
opm/simulators/wells/BlackoilWellModelGuideRates.hpp
|
||||
opm/simulators/wells/BlackoilWellModelNldd.hpp
|
||||
opm/simulators/wells/BlackoilWellModelNldd_impl.hpp
|
||||
opm/simulators/wells/BlackoilWellModelRestart.hpp
|
||||
opm/simulators/wells/BlackoilWellModelWBP.hpp
|
||||
opm/simulators/wells/ConnectionIndexMap.hpp
|
||||
|
163
opm/simulators/linalg/gpuistl/gpu_resources.hpp
Normal file
163
opm/simulators/linalg/gpuistl/gpu_resources.hpp
Normal file
@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright 2025 Equinor ASA
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OPM_SIMULATORS_LINALG_GPUISTL_GPU_RESOURCES_HPP
|
||||
#define OPM_SIMULATORS_LINALG_GPUISTL_GPU_RESOURCES_HPP
|
||||
#include <cuda.h>
|
||||
#include <cuda_runtime.h>
|
||||
#include <opm/simulators/linalg/gpuistl/detail/gpu_safe_call.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
/**
|
||||
* @brief Creates an RAII-style GPU resource class.
|
||||
*
|
||||
* This macro automatically generates a class that:
|
||||
* - Defines a resource type and a corresponding instance.
|
||||
* - Initializes the resource in the constructor via the provided creation function.
|
||||
* - Cleans up the resource in the destructor via the provided destruction function.
|
||||
*
|
||||
* @tparam name The class name to be defined.
|
||||
* @tparam type The underlying resource type to manage.
|
||||
* @tparam create The function used to create or allocate the resource.
|
||||
* @tparam destroy The function used to destroy or deallocate the resource.
|
||||
* @param ... Additional arguments forwarded to the creation function.
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* OPM_CREATE_GPU_RESOURCE(MyResource, ResourceType, createFunction, destroyFunction, args...);
|
||||
* @endcode
|
||||
*
|
||||
* This ensures correct setup and teardown of GPU resources without clutter in user code.
|
||||
*/
|
||||
#define OPM_CREATE_GPU_RESOURCE(name, type, create, destroy, ...) \
|
||||
class name \
|
||||
{ \
|
||||
public: \
|
||||
using resource_type = type; \
|
||||
\
|
||||
name() \
|
||||
{ \
|
||||
OPM_GPU_SAFE_CALL(create(&resource_, ##__VA_ARGS__)); \
|
||||
} \
|
||||
name(const name&) = delete; \
|
||||
name& operator=(const name&) = delete; \
|
||||
\
|
||||
~name() \
|
||||
{ \
|
||||
OPM_GPU_WARN_IF_ERROR(destroy(resource_)); \
|
||||
} \
|
||||
\
|
||||
const resource_type& get() const \
|
||||
{ \
|
||||
return resource_; \
|
||||
} \
|
||||
resource_type& get() \
|
||||
{ \
|
||||
return resource_; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
resource_type resource_ = nullptr; \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A helper macro for creating a GPU resource wrapper without invoking creation logic.
|
||||
*
|
||||
* This macro, closely related to \c OPM_CREATE_GPU_RESOURCE, provides a class that manages a GPU
|
||||
* resource of the specified type. Upon destruction, it automatically destroys the underlying
|
||||
* resource to ensure proper cleanup of GPU memory or handles.
|
||||
*
|
||||
* Usage:
|
||||
* - Construct an instance of this wrapper to store a GPU resource.
|
||||
* - The resource is destroyed when the wrapper goes out of scope.
|
||||
*
|
||||
* Use \c OPM_CREATE_GPU_RESOURCE for variants that require resource creation logic.
|
||||
*
|
||||
* @tparam name Name of the wrapper class to manage the GPU resource.
|
||||
* @tparam type The type of the GPU resource to manage.
|
||||
* @tparam destroy The function or macro used to destroy the resource.
|
||||
*/
|
||||
#define OPM_CREATE_GPU_RESOURCE_NO_CREATE(name, type, destroy) \
|
||||
class name \
|
||||
{ \
|
||||
public: \
|
||||
using resource_type = type; \
|
||||
\
|
||||
name() = default; \
|
||||
\
|
||||
~name() \
|
||||
{ \
|
||||
OPM_GPU_WARN_IF_ERROR(destroy(resource_)); \
|
||||
} \
|
||||
name(const name&) = delete; \
|
||||
name& operator=(const name&) = delete; \
|
||||
\
|
||||
const resource_type& get() const \
|
||||
{ \
|
||||
return resource_; \
|
||||
} \
|
||||
resource_type& get() \
|
||||
{ \
|
||||
return resource_; \
|
||||
} \
|
||||
\
|
||||
private: \
|
||||
resource_type resource_; \
|
||||
}
|
||||
|
||||
namespace Opm::gpuistl
|
||||
{
|
||||
/**
|
||||
* @brief Manages a CUDA stream resource.
|
||||
*
|
||||
* This resource encapsulates a cudaStream_t handle and provides
|
||||
* automatic creation and destruction of the CUDA stream.
|
||||
* Use this resource to schedule and synchronize GPU kernels
|
||||
* or other asynchronous operations.
|
||||
*/
|
||||
OPM_CREATE_GPU_RESOURCE(GPUStream, cudaStream_t, cudaStreamCreate, cudaStreamDestroy);
|
||||
|
||||
/**
|
||||
* @brief Manages a CUDA event resource.
|
||||
*
|
||||
* This resource encapsulates a cudaEvent_t handle and provides
|
||||
* automatic creation and destruction of the CUDA event.
|
||||
* Use this resource to measure elapsed time or synchronize
|
||||
* GPU executions between different streams.
|
||||
*/
|
||||
OPM_CREATE_GPU_RESOURCE(GPUEvent, cudaEvent_t, cudaEventCreate, cudaEventDestroy);
|
||||
|
||||
/**
|
||||
* @brief Manages a CUDA graph resource.
|
||||
*
|
||||
* This resource encapsulates a cudaGraph_t handle and provides
|
||||
* automatic creation and destruction of a CUDA graph.
|
||||
* It represents a series of operations captured for
|
||||
* efficient replay, execution, or modification.
|
||||
*/
|
||||
OPM_CREATE_GPU_RESOURCE(
|
||||
GPUGraph, cudaGraph_t, cudaGraphCreate, cudaGraphDestroy, 0); // Per documentation, needs 0 as last argument
|
||||
|
||||
/**
|
||||
* @brief Manages a CUDA graph execution resource.
|
||||
*
|
||||
* This resource encapsulates a cudaGraphExec_t handle and provides
|
||||
* automatic destruction of the CUDA graph execution object.
|
||||
* It represents the compiled and optimized version of a CUDA graph
|
||||
* ready for efficient execution.
|
||||
*/
|
||||
OPM_CREATE_GPU_RESOURCE_NO_CREATE(GPUGraphExec, cudaGraphExec_t, cudaGraphExecDestroy);
|
||||
} // namespace Opm::gpuistl
|
||||
#endif
|
75
tests/gpuistl/test_gpu_resources.cu
Normal file
75
tests/gpuistl/test_gpu_resources.cu
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2025 Equinor ASA
|
||||
|
||||
This file is part of the Open Porous Media project (OPM).
|
||||
|
||||
OPM is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OPM is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <config.h>
|
||||
#include <opm/simulators/linalg/gpuistl/gpu_resources.hpp>
|
||||
|
||||
#define BOOST_TEST_MODULE TestGPUResources
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <cuda_runtime.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
__global__ void
|
||||
dummyKernel()
|
||||
{
|
||||
}
|
||||
} // namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestStreams)
|
||||
{
|
||||
using namespace Opm::gpuistl;
|
||||
BOOST_CHECK_NO_THROW(GPUStream());
|
||||
auto stream = GPUStream();
|
||||
BOOST_CHECK(stream.get() != nullptr);
|
||||
|
||||
// Check that we can launch a kernel with said stream
|
||||
|
||||
dummyKernel<<<1, 1, 0, stream.get()>>>();
|
||||
OPM_GPU_SAFE_CALL(cudaDeviceSynchronize());
|
||||
OPM_GPU_SAFE_CALL(cudaGetLastError());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestEvents)
|
||||
{
|
||||
using namespace Opm::gpuistl;
|
||||
BOOST_CHECK_NO_THROW(GPUEvent());
|
||||
auto event = GPUEvent();
|
||||
BOOST_CHECK(event.get() != nullptr);
|
||||
|
||||
// Check that we can record and wait for said event
|
||||
|
||||
OPM_GPU_SAFE_CALL(cudaEventRecord(event.get()));
|
||||
OPM_GPU_SAFE_CALL(cudaEventSynchronize(event.get()));
|
||||
OPM_GPU_SAFE_CALL(cudaGetLastError());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestGraph)
|
||||
{
|
||||
using namespace Opm::gpuistl;
|
||||
BOOST_CHECK_NO_THROW(GPUGraph());
|
||||
auto graph = GPUGraph();
|
||||
BOOST_CHECK(graph.get() != nullptr);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestGraphExec)
|
||||
{
|
||||
using namespace Opm::gpuistl;
|
||||
BOOST_CHECK_NO_THROW(GPUGraphExec());
|
||||
}
|
Loading…
Reference in New Issue
Block a user