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