Actual source code: cupmdevice.cxx
1: #include "../../interface/cupmdevice.hpp"
3: namespace Petsc {
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;
13: public:
14: // default constructor
15: explicit PetscDeviceInternal(int dev) noexcept : _id{dev} {}
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;
24: cerr = cupmGetDeviceProperties(&this->_dprop,this->_id);CHKERRCUPM(cerr);
25: return(0);
26: }
28: PETSC_NODISCARD int id() const noexcept { return this->_id;}
29: PETSC_NODISCARD const cupmDeviceProp_t& deviceProp() const noexcept { return this->_dprop;}
30: };
32: template <CUPMDeviceKind T>
33: PetscErrorCode CUPMDevice<T>::__initialize() noexcept
34: {
35: int ndev;
36: cupmError_t cerr;
39: if (_initialized) return(0);
40: cerr = cupmGetDeviceCount(&ndev);CHKERRCUPM(cerr);
41: CHKERRCXX(_devices.reserve(ndev));
42: for (int i = 0; i < ndev; ++i) {
45: CHKERRCXX(_devices.emplace_back(std::unique_ptr<PetscDeviceInternal>{new PetscDeviceInternal{i}}));
46: _devices[i]->initialize();
47: }
48: CHKERRCXX(_devices.shrink_to_fit());
49: _initialized = PETSC_TRUE;
50: return(0);
51: }
53: template <CUPMDeviceKind T>
54: PetscErrorCode CUPMDevice<T>::getDevice(PetscDevice &device) noexcept
55: {
59: this->__initialize();
60: // default device is always the first device for now?
61: device->deviceId = this->_devices[0]->id();
62: device->ops->createcontext = this->_create;
63: return(0);
64: }
66: template <CUPMDeviceKind T>
67: PetscErrorCode CUPMDevice<T>::configureDevice(PetscDevice &device) noexcept
68: {
69: cupmError_t cerr;
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: return(0);
78: }
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
88: } // namespace Petsc