xref: /petsc/src/sys/objects/device/impls/cupm/cupmdevice.cxx (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
1*030f984aSJacob Faibussowitsch #include "../../interface/cupmdevice.hpp"
2*030f984aSJacob Faibussowitsch 
3*030f984aSJacob Faibussowitsch namespace Petsc {
4*030f984aSJacob Faibussowitsch 
5*030f984aSJacob Faibussowitsch // internal "impls" class for CUPMDevice. Each instance represents a single cupm device
6*030f984aSJacob Faibussowitsch template <CUPMDeviceKind T>
7*030f984aSJacob Faibussowitsch class CUPMDevice<T>::PetscDeviceInternal
8*030f984aSJacob Faibussowitsch {
9*030f984aSJacob Faibussowitsch private:
10*030f984aSJacob Faibussowitsch   const int        _id;
11*030f984aSJacob Faibussowitsch   cupmDeviceProp_t _dprop;
12*030f984aSJacob Faibussowitsch 
13*030f984aSJacob Faibussowitsch public:
14*030f984aSJacob Faibussowitsch   // default constructor
15*030f984aSJacob Faibussowitsch   explicit PetscDeviceInternal(int dev) noexcept : _id{dev} {}
16*030f984aSJacob Faibussowitsch 
17*030f984aSJacob Faibussowitsch   // gather all relevant information for a particular device, a cupmDeviceProp_t is
18*030f984aSJacob Faibussowitsch   // usually sufficient here
19*030f984aSJacob Faibussowitsch   PETSC_NODISCARD PetscErrorCode initialize() noexcept
20*030f984aSJacob Faibussowitsch   {
21*030f984aSJacob Faibussowitsch     cupmError_t cerr;
22*030f984aSJacob Faibussowitsch 
23*030f984aSJacob Faibussowitsch     PetscFunctionBegin;
24*030f984aSJacob Faibussowitsch     cerr = cupmGetDeviceProperties(&this->_dprop,this->_id);CHKERRCUPM(cerr);
25*030f984aSJacob Faibussowitsch     PetscFunctionReturn(0);
26*030f984aSJacob Faibussowitsch   }
27*030f984aSJacob Faibussowitsch 
28*030f984aSJacob Faibussowitsch   PETSC_NODISCARD int id() const noexcept { return this->_id;}
29*030f984aSJacob Faibussowitsch   PETSC_NODISCARD const cupmDeviceProp_t& deviceProp() const noexcept { return this->_dprop;}
30*030f984aSJacob Faibussowitsch };
31*030f984aSJacob Faibussowitsch 
32*030f984aSJacob Faibussowitsch template <CUPMDeviceKind T>
33*030f984aSJacob Faibussowitsch PetscErrorCode CUPMDevice<T>::__initialize() noexcept
34*030f984aSJacob Faibussowitsch {
35*030f984aSJacob Faibussowitsch   int         ndev;
36*030f984aSJacob Faibussowitsch   cupmError_t cerr;
37*030f984aSJacob Faibussowitsch 
38*030f984aSJacob Faibussowitsch   PetscFunctionBegin;
39*030f984aSJacob Faibussowitsch   if (_initialized) PetscFunctionReturn(0);
40*030f984aSJacob Faibussowitsch   cerr = cupmGetDeviceCount(&ndev);CHKERRCUPM(cerr);
41*030f984aSJacob Faibussowitsch   CHKERRCXX(_devices.reserve(ndev));
42*030f984aSJacob Faibussowitsch   for (int i = 0; i < ndev; ++i) {
43*030f984aSJacob Faibussowitsch     PetscErrorCode ierr;
44*030f984aSJacob Faibussowitsch 
45*030f984aSJacob Faibussowitsch     CHKERRCXX(_devices.emplace_back(std::unique_ptr<PetscDeviceInternal>{new PetscDeviceInternal{i}}));
46*030f984aSJacob Faibussowitsch     ierr = _devices[i]->initialize();CHKERRQ(ierr);
47*030f984aSJacob Faibussowitsch   }
48*030f984aSJacob Faibussowitsch   CHKERRCXX(_devices.shrink_to_fit());
49*030f984aSJacob Faibussowitsch   _initialized = PETSC_TRUE;
50*030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
51*030f984aSJacob Faibussowitsch }
52*030f984aSJacob Faibussowitsch 
53*030f984aSJacob Faibussowitsch template <CUPMDeviceKind T>
54*030f984aSJacob Faibussowitsch PetscErrorCode CUPMDevice<T>::getDevice(PetscDevice &device) noexcept
55*030f984aSJacob Faibussowitsch {
56*030f984aSJacob Faibussowitsch   PetscErrorCode ierr;
57*030f984aSJacob Faibussowitsch 
58*030f984aSJacob Faibussowitsch   PetscFunctionBegin;
59*030f984aSJacob Faibussowitsch   ierr = this->__initialize();CHKERRQ(ierr);
60*030f984aSJacob Faibussowitsch   // default device is always the first device for now?
61*030f984aSJacob Faibussowitsch   device->deviceId = this->_devices[0]->id();
62*030f984aSJacob Faibussowitsch   device->ops->createcontext = this->_create;
63*030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
64*030f984aSJacob Faibussowitsch }
65*030f984aSJacob Faibussowitsch 
66*030f984aSJacob Faibussowitsch template <CUPMDeviceKind T>
67*030f984aSJacob Faibussowitsch PetscErrorCode CUPMDevice<T>::configureDevice(PetscDevice &device) noexcept
68*030f984aSJacob Faibussowitsch {
69*030f984aSJacob Faibussowitsch   cupmError_t cerr;
70*030f984aSJacob Faibussowitsch 
71*030f984aSJacob Faibussowitsch   PetscFunctionBegin;
72*030f984aSJacob Faibussowitsch   cerr = cupmSetDevice(device->deviceId);
73*030f984aSJacob Faibussowitsch   // why on EARTH nvidia insists on making otherwise informational states into
74*030f984aSJacob Faibussowitsch   // fully-fledged error codes is beyond me. Why couldn't a pointer to bool argument have
75*030f984aSJacob Faibussowitsch   // sufficed?!?!?!
76*030f984aSJacob Faibussowitsch   if (cerr != cupmErrorDeviceAlreadyInUse) CHKERRCUPM(cerr);
77*030f984aSJacob Faibussowitsch   PetscFunctionReturn(0);
78*030f984aSJacob Faibussowitsch }
79*030f984aSJacob Faibussowitsch 
80*030f984aSJacob Faibussowitsch // explicitly instantiate the classes
81*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA)
82*030f984aSJacob Faibussowitsch template class CUPMDevice<CUPMDeviceKind::CUDA>;
83*030f984aSJacob Faibussowitsch #endif
84*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP)
85*030f984aSJacob Faibussowitsch template class CUPMDevice<CUPMDeviceKind::HIP>;
86*030f984aSJacob Faibussowitsch #endif
87*030f984aSJacob Faibussowitsch 
88*030f984aSJacob Faibussowitsch } // namespace Petsc
89