Date: 2022-03-04T17:37:10+00:00

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