1*030f984aSJacob Faibussowitsch #include "cupmdevice.hpp" /* I "petscdevice.h" */ 2*030f984aSJacob Faibussowitsch 3*030f984aSJacob Faibussowitsch using namespace Petsc; 4*030f984aSJacob Faibussowitsch 5*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) 6*030f984aSJacob Faibussowitsch static CUPMDevice<CUPMDeviceKind::CUDA> cudaDevice(PetscDeviceContextCreate_CUDA); 7*030f984aSJacob Faibussowitsch #endif 8*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP) 9*030f984aSJacob Faibussowitsch static CUPMDevice<CUPMDeviceKind::HIP> hipDevice(PetscDeviceContextCreate_HIP); 10*030f984aSJacob Faibussowitsch #endif 11*030f984aSJacob Faibussowitsch 12*030f984aSJacob Faibussowitsch const char *const PetscDeviceKinds[] = {"invalid","cuda","hip","default","max","PetscDeviceKind","PETSC_DEVICE_",PETSC_NULLPTR}; 13*030f984aSJacob Faibussowitsch 14*030f984aSJacob Faibussowitsch /*@C 15*030f984aSJacob Faibussowitsch PetscDeviceCreate - Get a new handle for a particular device kind 16*030f984aSJacob Faibussowitsch 17*030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 18*030f984aSJacob Faibussowitsch 19*030f984aSJacob Faibussowitsch Input Parameter: 20*030f984aSJacob Faibussowitsch . kind - The kind of PetscDevice 21*030f984aSJacob Faibussowitsch 22*030f984aSJacob Faibussowitsch Output Parameter: 23*030f984aSJacob Faibussowitsch . device - The PetscDevice 24*030f984aSJacob Faibussowitsch 25*030f984aSJacob Faibussowitsch Notes: 26*030f984aSJacob Faibussowitsch If this is the first time that a PetscDevice is created, this routine may initialize 27*030f984aSJacob Faibussowitsch the corresponding backend. If this is the case, this will most likely cause some sort of 28*030f984aSJacob Faibussowitsch device synchronization. 29*030f984aSJacob Faibussowitsch 30*030f984aSJacob Faibussowitsch Level: beginner 31*030f984aSJacob Faibussowitsch 32*030f984aSJacob Faibussowitsch .seealso: PetscDeviceConfigure(), PetscDeviceDestroy() 33*030f984aSJacob Faibussowitsch @*/ 34*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceCreate(PetscDeviceKind kind, PetscDevice *device) 35*030f984aSJacob Faibussowitsch { 36*030f984aSJacob Faibussowitsch static PetscInt PetscDeviceCounter = 0; 37*030f984aSJacob Faibussowitsch PetscDevice dev; 38*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 39*030f984aSJacob Faibussowitsch 40*030f984aSJacob Faibussowitsch PetscFunctionBegin; 41*030f984aSJacob Faibussowitsch PetscValidDeviceKind(kind,1); 42*030f984aSJacob Faibussowitsch PetscValidPointer(device,2); 43*030f984aSJacob Faibussowitsch ierr = PetscNew(&dev);CHKERRQ(ierr); 44*030f984aSJacob Faibussowitsch dev->id = PetscDeviceCounter++; 45*030f984aSJacob Faibussowitsch dev->kind = kind; 46*030f984aSJacob Faibussowitsch switch (kind) { 47*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) 48*030f984aSJacob Faibussowitsch case PETSC_DEVICE_CUDA: 49*030f984aSJacob Faibussowitsch ierr = cudaDevice.getDevice(dev);CHKERRQ(ierr); 50*030f984aSJacob Faibussowitsch break; 51*030f984aSJacob Faibussowitsch #endif 52*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP) 53*030f984aSJacob Faibussowitsch case PETSC_DEVICE_HIP: 54*030f984aSJacob Faibussowitsch ierr = hipDevice.getDevice(dev);CHKERRQ(ierr); 55*030f984aSJacob Faibussowitsch break; 56*030f984aSJacob Faibussowitsch #endif 57*030f984aSJacob Faibussowitsch default: 58*030f984aSJacob Faibussowitsch SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Must have configured PETSc with %s support to use PetscDeviceKind %d",PetscDeviceKinds[kind],kind); 59*030f984aSJacob Faibussowitsch break; 60*030f984aSJacob Faibussowitsch } 61*030f984aSJacob Faibussowitsch *device = dev; 62*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 63*030f984aSJacob Faibussowitsch } 64*030f984aSJacob Faibussowitsch 65*030f984aSJacob Faibussowitsch /*@C 66*030f984aSJacob Faibussowitsch PetscDeviceConfigure - Configure a particular PetscDevice 67*030f984aSJacob Faibussowitsch 68*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 69*030f984aSJacob Faibussowitsch 70*030f984aSJacob Faibussowitsch Input Parameter: 71*030f984aSJacob Faibussowitsch . device - The PetscDevice to Configure 72*030f984aSJacob Faibussowitsch 73*030f984aSJacob Faibussowitsch Developer Notes: 74*030f984aSJacob Faibussowitsch Currently a no-op 75*030f984aSJacob Faibussowitsch 76*030f984aSJacob Faibussowitsch Level: developer 77*030f984aSJacob Faibussowitsch 78*030f984aSJacob Faibussowitsch .seealso: PetscDeviceCreate(), PetscDeviceDestroy() 79*030f984aSJacob Faibussowitsch @*/ 80*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceConfigure(PetscDevice device) 81*030f984aSJacob Faibussowitsch { 82*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) || PetscDefined(HAVE_HIP) 83*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 84*030f984aSJacob Faibussowitsch #endif 85*030f984aSJacob Faibussowitsch 86*030f984aSJacob Faibussowitsch PetscFunctionBegin; 87*030f984aSJacob Faibussowitsch PetscValidDevice(device,1); 88*030f984aSJacob Faibussowitsch switch (device->kind) { 89*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) 90*030f984aSJacob Faibussowitsch case PETSC_DEVICE_CUDA: 91*030f984aSJacob Faibussowitsch ierr = cudaDevice.configureDevice(device);CHKERRQ(ierr); 92*030f984aSJacob Faibussowitsch break; 93*030f984aSJacob Faibussowitsch #endif 94*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP) 95*030f984aSJacob Faibussowitsch case PETSC_DEVICE_HIP: 96*030f984aSJacob Faibussowitsch ierr = hipDevice.configureDevice(device);CHKERRQ(ierr); 97*030f984aSJacob Faibussowitsch break; 98*030f984aSJacob Faibussowitsch #endif 99*030f984aSJacob Faibussowitsch default: 100*030f984aSJacob Faibussowitsch SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"Must have configured PETSc with %s support to use PetscDeviceKind %d",PetscDeviceKinds[device->kind],device->kind); 101*030f984aSJacob Faibussowitsch break; 102*030f984aSJacob Faibussowitsch } 103*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 104*030f984aSJacob Faibussowitsch } 105*030f984aSJacob Faibussowitsch 106*030f984aSJacob Faibussowitsch /*@C 107*030f984aSJacob Faibussowitsch PetscDeviceDestroy - Free a PetscDevice 108*030f984aSJacob Faibussowitsch 109*030f984aSJacob Faibussowitsch Not Collective, Asynchronous 110*030f984aSJacob Faibussowitsch 111*030f984aSJacob Faibussowitsch Input Parameter: 112*030f984aSJacob Faibussowitsch . device - The PetscDevice 113*030f984aSJacob Faibussowitsch 114*030f984aSJacob Faibussowitsch Level: beginner 115*030f984aSJacob Faibussowitsch 116*030f984aSJacob Faibussowitsch .seealso: PetscDeviceCreate(), PetscDeviceConfigure() 117*030f984aSJacob Faibussowitsch @*/ 118*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceDestroy(PetscDevice *device) 119*030f984aSJacob Faibussowitsch { 120*030f984aSJacob Faibussowitsch PetscFunctionBegin; 121*030f984aSJacob Faibussowitsch if (!*device) PetscFunctionReturn(0); 122*030f984aSJacob Faibussowitsch if (!--(*device)->refcnt) { 123*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 124*030f984aSJacob Faibussowitsch 125*030f984aSJacob Faibussowitsch if (PetscUnlikelyDebug((*device)->refcnt < 0)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"PetscDevice %D reference count %D < 0",(*device)->id,(*device)->refcnt); 126*030f984aSJacob Faibussowitsch ierr = PetscFree(*device);CHKERRQ(ierr); 127*030f984aSJacob Faibussowitsch } 128*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 129*030f984aSJacob Faibussowitsch } 130*030f984aSJacob Faibussowitsch 131*030f984aSJacob Faibussowitsch static PetscDevice defaultDevices[PETSC_DEVICE_MAX]; 132*030f984aSJacob Faibussowitsch 133*030f984aSJacob Faibussowitsch static PetscErrorCode InitializeDeviceHelper_Private(PetscDeviceKind kind, bool supported = false) 134*030f984aSJacob Faibussowitsch { 135*030f984aSJacob Faibussowitsch const int kindIdx = static_cast<int>(kind); 136*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 137*030f984aSJacob Faibussowitsch 138*030f984aSJacob Faibussowitsch PetscFunctionBegin; 139*030f984aSJacob Faibussowitsch if (supported) { 140*030f984aSJacob Faibussowitsch /* on the off chance that someone fumbles calling this with INVALID or MAX */ 141*030f984aSJacob Faibussowitsch PetscValidDeviceKind(kind,1); 142*030f984aSJacob Faibussowitsch ierr = PetscInfo1(NULL,"PetscDeviceKind %s supported, initializing\n",PetscDeviceKinds[kindIdx]);CHKERRQ(ierr); 143*030f984aSJacob Faibussowitsch ierr = PetscDeviceCreate(kind,defaultDevices+kindIdx);CHKERRQ(ierr); 144*030f984aSJacob Faibussowitsch ierr = PetscDeviceConfigure(defaultDevices[kindIdx]);CHKERRQ(ierr); 145*030f984aSJacob Faibussowitsch /* the default devices are all automatically "referenced" at least once, otherwise the 146*030f984aSJacob Faibussowitsch reference counting is off for them. We could alternatively increase the reference 147*030f984aSJacob Faibussowitsch count when they are retrieved but that is a lot more brittle; whats to stop someone 148*030f984aSJacob Faibussowitsch from doing thhe following? 149*030f984aSJacob Faibussowitsch 150*030f984aSJacob Faibussowitsch for (int i = 0; i < 10000; ++i) auto device = PetscDeviceDefault_Internal(); 151*030f984aSJacob Faibussowitsch */ 152*030f984aSJacob Faibussowitsch defaultDevices[kindIdx] = PetscDeviceReference(defaultDevices[kindIdx]); 153*030f984aSJacob Faibussowitsch } else { 154*030f984aSJacob Faibussowitsch ierr = PetscInfo1(NULL,"PetscDeviceKind %s not supported\n",PetscDeviceKinds[kindIdx]);CHKERRQ(ierr); 155*030f984aSJacob Faibussowitsch defaultDevices[kindIdx] = PETSC_NULLPTR; 156*030f984aSJacob Faibussowitsch } 157*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 158*030f984aSJacob Faibussowitsch } 159*030f984aSJacob Faibussowitsch 160*030f984aSJacob Faibussowitsch /* called from PetscFinalize() do not call yourself! */ 161*030f984aSJacob Faibussowitsch static PetscErrorCode PetscDeviceFinalizeDefaultDevices_Private(void) 162*030f984aSJacob Faibussowitsch { 163*030f984aSJacob Faibussowitsch const int maxIdx = static_cast<int>(PETSC_DEVICE_MAX); 164*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 165*030f984aSJacob Faibussowitsch 166*030f984aSJacob Faibussowitsch PetscFunctionBegin; 167*030f984aSJacob Faibussowitsch for (int i = 0; i < maxIdx; ++i) {ierr = PetscDeviceDestroy(defaultDevices+i);CHKERRQ(ierr);} 168*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 169*030f984aSJacob Faibussowitsch } 170*030f984aSJacob Faibussowitsch 171*030f984aSJacob Faibussowitsch /* called from PetscInitialize() do not call yourself! */ 172*030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceInitializeDefaultDevices_Internal(void) 173*030f984aSJacob Faibussowitsch { 174*030f984aSJacob Faibussowitsch PetscErrorCode ierr; 175*030f984aSJacob Faibussowitsch 176*030f984aSJacob Faibussowitsch PetscFunctionBegin; 177*030f984aSJacob Faibussowitsch ierr = PetscRegisterFinalize(PetscDeviceFinalizeDefaultDevices_Private);CHKERRQ(ierr); 178*030f984aSJacob Faibussowitsch ierr = InitializeDeviceHelper_Private(PETSC_DEVICE_INVALID);CHKERRQ(ierr); 179*030f984aSJacob Faibussowitsch ierr = InitializeDeviceHelper_Private(PETSC_DEVICE_CUDA,PetscDefined(HAVE_CUDA));CHKERRQ(ierr); 180*030f984aSJacob Faibussowitsch ierr = InitializeDeviceHelper_Private(PETSC_DEVICE_HIP,PetscDefined(HAVE_HIP));CHKERRQ(ierr); 181*030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 182*030f984aSJacob Faibussowitsch } 183*030f984aSJacob Faibussowitsch 184*030f984aSJacob Faibussowitsch /* Get the default PetscDevice for a particular kind, usually one should use 185*030f984aSJacob Faibussowitsch PetscDeviceDefault_Internal() since that will return the automatically selected 186*030f984aSJacob Faibussowitsch default kind. */ 187*030f984aSJacob Faibussowitsch PetscDevice PetscDeviceDefaultKind_Internal(PetscDeviceKind kind) 188*030f984aSJacob Faibussowitsch { 189*030f984aSJacob Faibussowitsch return defaultDevices[static_cast<int>(kind)]; 190*030f984aSJacob Faibussowitsch } 191