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