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