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