1030f984aSJacob Faibussowitsch #include "cupmdevice.hpp" /* I "petscdevice.h" */ 2030f984aSJacob Faibussowitsch 3030f984aSJacob Faibussowitsch using namespace Petsc; 4030f984aSJacob Faibussowitsch 5a4af0ceeSJacob Faibussowitsch /* note to anyone adding more classes, the name must be ALL_CAPS_SHORT_NAME + Device exactly to 6a4af0ceeSJacob Faibussowitsch * be picked up by the switch-case macros below. */ 7030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) 8a4af0ceeSJacob Faibussowitsch static CUPMDevice<CUPMDeviceType::CUDA> CUDADevice(PetscDeviceContextCreate_CUDA); 9030f984aSJacob Faibussowitsch #endif 10030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP) 11a4af0ceeSJacob Faibussowitsch static CUPMDevice<CUPMDeviceType::HIP> HIPDevice(PetscDeviceContextCreate_HIP); 12030f984aSJacob Faibussowitsch #endif 13030f984aSJacob Faibussowitsch 14a4af0ceeSJacob Faibussowitsch const char *const PetscDeviceTypes[] = { 15a4af0ceeSJacob Faibussowitsch "invalid", 16a4af0ceeSJacob Faibussowitsch "cuda", 17a4af0ceeSJacob Faibussowitsch "hip", 18a4af0ceeSJacob Faibussowitsch "max", 19a4af0ceeSJacob Faibussowitsch "PetscDeviceType", 20a4af0ceeSJacob Faibussowitsch "PETSC_DEVICE_", 21a4af0ceeSJacob Faibussowitsch PETSC_NULLPTR 22a4af0ceeSJacob Faibussowitsch }; 23a4af0ceeSJacob Faibussowitsch 24a4af0ceeSJacob Faibussowitsch const char *const PetscDeviceInitTypes[] = { 25a4af0ceeSJacob Faibussowitsch "none", 26a4af0ceeSJacob Faibussowitsch "lazy", 27a4af0ceeSJacob Faibussowitsch "eager", 28a4af0ceeSJacob Faibussowitsch "PetscDeviceInitType", 29a4af0ceeSJacob Faibussowitsch "PETSC_DEVICE_INIT_", 30a4af0ceeSJacob Faibussowitsch PETSC_NULLPTR 31a4af0ceeSJacob Faibussowitsch }; 32a4af0ceeSJacob Faibussowitsch static_assert( 33a4af0ceeSJacob Faibussowitsch sizeof(PetscDeviceInitTypes)/sizeof(*PetscDeviceInitTypes) == 6, 34a4af0ceeSJacob Faibussowitsch "Must change CUPMDevice<T>::initialize number of enum values in -device_enable_cupm to match!" 35a4af0ceeSJacob Faibussowitsch ); 36a4af0ceeSJacob Faibussowitsch 37a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_DEFAULT_CASE(comm,type) \ 38a4af0ceeSJacob Faibussowitsch SETERRQ1((comm),PETSC_ERR_PLIB, \ 39a4af0ceeSJacob Faibussowitsch "PETSc was seemingly configured for PetscDeviceType %s but " \ 40a4af0ceeSJacob Faibussowitsch "we've fallen through all cases in a switch", \ 41a4af0ceeSJacob Faibussowitsch PetscDeviceTypes[type]) 42a4af0ceeSJacob Faibussowitsch 43a4af0ceeSJacob Faibussowitsch #define CAT_(a,...) a ## __VA_ARGS__ 44a4af0ceeSJacob Faibussowitsch #define CAT(a,...) CAT_(a,__VA_ARGS__) 45a4af0ceeSJacob Faibussowitsch 46a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CASE_IF_PETSC_DEFINED__0(IMPLS,func,...) 47a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CASE_IF_PETSC_DEFINED__1(IMPLS,func,...) \ 48a4af0ceeSJacob Faibussowitsch case CAT(PETSC_DEVICE_,IMPLS): \ 49a4af0ceeSJacob Faibussowitsch { \ 50a4af0ceeSJacob Faibussowitsch auto ierr = CAT(IMPLS,Device).func(__VA_ARGS__);CHKERRQ(ierr); \ 51a4af0ceeSJacob Faibussowitsch break; \ 52a4af0ceeSJacob Faibussowitsch } 53a4af0ceeSJacob Faibussowitsch 54a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CASE_IF_PETSC_DEFINED_(IMPLS,...) \ 55a4af0ceeSJacob Faibussowitsch CAT(PETSC_DEVICE_CASE_IF_PETSC_DEFINED__,PetscDefined(CAT(HAVE_,IMPLS)))(IMPLS,__VA_ARGS__) 56a4af0ceeSJacob Faibussowitsch 57a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_CASE_IF_PETSC_DEFINED(IMPLS,...) \ 58a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_CASE_IF_PETSC_DEFINED_(IMPLS,__VA_ARGS__) 59a4af0ceeSJacob Faibussowitsch 60a4af0ceeSJacob Faibussowitsch #define PETSC_DEVICE_UNUSED_IF_NO_DEVICE(var) (void)(var) 61030f984aSJacob Faibussowitsch 62030f984aSJacob Faibussowitsch /*@C 63a4af0ceeSJacob Faibussowitsch PetscDeviceCreate - Get a new handle for a particular device type 64030f984aSJacob Faibussowitsch 65030f984aSJacob Faibussowitsch Not Collective, Possibly Synchronous 66030f984aSJacob Faibussowitsch 67030f984aSJacob Faibussowitsch Input Parameter: 68a4af0ceeSJacob Faibussowitsch . type - The type of PetscDevice 69a4af0ceeSJacob Faibussowitsch . devid - The numeric ID# of the device (pass PETSC_DECIDE to assign automatically) 70030f984aSJacob Faibussowitsch 71030f984aSJacob Faibussowitsch Output Parameter: 72030f984aSJacob Faibussowitsch . device - The PetscDevice 73030f984aSJacob Faibussowitsch 74030f984aSJacob Faibussowitsch Notes: 75a4af0ceeSJacob Faibussowitsch This routine may initialize PetscDevice. If this is the case, this will most likely cause 76a4af0ceeSJacob Faibussowitsch some sort of device synchronization. 77a4af0ceeSJacob Faibussowitsch 78a4af0ceeSJacob Faibussowitsch devid is what you might pass to cudaSetDevice() for example. 79030f984aSJacob Faibussowitsch 80030f984aSJacob Faibussowitsch Level: beginner 81030f984aSJacob Faibussowitsch 82a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceInitType, PetscDeviceInitialize(), 83a4af0ceeSJacob Faibussowitsch PetscDeviceInitialized(), PetscDeviceConfigure(), PetscDeviceView(), PetscDeviceDestroy() 84030f984aSJacob Faibussowitsch @*/ 85a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceCreate(PetscDeviceType type, PetscInt devid, PetscDevice *device) 86030f984aSJacob Faibussowitsch { 87030f984aSJacob Faibussowitsch static PetscInt PetscDeviceCounter = 0; 88030f984aSJacob Faibussowitsch PetscDevice dev; 89030f984aSJacob Faibussowitsch PetscErrorCode ierr; 90030f984aSJacob Faibussowitsch 91030f984aSJacob Faibussowitsch PetscFunctionBegin; 92a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type,1); 93a4af0ceeSJacob Faibussowitsch PetscValidPointer(device,3); 94a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitializePackage();CHKERRQ(ierr); 95030f984aSJacob Faibussowitsch ierr = PetscNew(&dev);CHKERRQ(ierr); 96030f984aSJacob Faibussowitsch dev->id = PetscDeviceCounter++; 97a4af0ceeSJacob Faibussowitsch dev->type = type; 98a4af0ceeSJacob Faibussowitsch dev->refcnt = 1; 99a4af0ceeSJacob Faibussowitsch /* if you are adding a device, you also need to add it's initialization in 100a4af0ceeSJacob Faibussowitsch PetscDeviceInitializeTypeFromOptions_Private() below */ 101a4af0ceeSJacob Faibussowitsch switch (type) { 102a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_CASE_IF_PETSC_DEFINED(CUDA,getDevice,dev,devid); 103a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_CASE_IF_PETSC_DEFINED(HIP,getDevice,dev,devid); 104030f984aSJacob Faibussowitsch default: 105a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_UNUSED_IF_NO_DEVICE(devid); 106a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_DEFAULT_CASE(PETSC_COMM_SELF,type); 107030f984aSJacob Faibussowitsch } 108030f984aSJacob Faibussowitsch *device = dev; 109030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 110030f984aSJacob Faibussowitsch } 111030f984aSJacob Faibussowitsch 112030f984aSJacob Faibussowitsch /*@C 113030f984aSJacob Faibussowitsch PetscDeviceDestroy - Free a PetscDevice 114030f984aSJacob Faibussowitsch 115030f984aSJacob Faibussowitsch Not Collective, Asynchronous 116030f984aSJacob Faibussowitsch 117030f984aSJacob Faibussowitsch Input Parameter: 118030f984aSJacob Faibussowitsch . device - The PetscDevice 119030f984aSJacob Faibussowitsch 120030f984aSJacob Faibussowitsch Level: beginner 121030f984aSJacob Faibussowitsch 122a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceCreate(), PetscDeviceConfigure(), PetscDeviceView() 123030f984aSJacob Faibussowitsch @*/ 124030f984aSJacob Faibussowitsch PetscErrorCode PetscDeviceDestroy(PetscDevice *device) 125030f984aSJacob Faibussowitsch { 126030f984aSJacob Faibussowitsch PetscErrorCode ierr; 127030f984aSJacob Faibussowitsch 128a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 129a4af0ceeSJacob Faibussowitsch if (!*device) PetscFunctionReturn(0); 130a4af0ceeSJacob Faibussowitsch PetscValidDevice(*device,1); 131a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceDereference_Internal(*device);CHKERRQ(ierr); 132a4af0ceeSJacob Faibussowitsch if ((*device)->refcnt) { 133a4af0ceeSJacob Faibussowitsch *device = PETSC_NULLPTR; 134a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 135030f984aSJacob Faibussowitsch } 136a4af0ceeSJacob Faibussowitsch ierr = PetscFree((*device)->data);CHKERRQ(ierr); 137a4af0ceeSJacob Faibussowitsch ierr = PetscFree(*device);CHKERRQ(ierr); 138030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 139030f984aSJacob Faibussowitsch } 140030f984aSJacob Faibussowitsch 141a4af0ceeSJacob Faibussowitsch /*@C 142a4af0ceeSJacob Faibussowitsch PetscDeviceConfigure - Configure a particular PetscDevice 143030f984aSJacob Faibussowitsch 144a4af0ceeSJacob Faibussowitsch Not Collective, Asynchronous 145a4af0ceeSJacob Faibussowitsch 146a4af0ceeSJacob Faibussowitsch Input Parameter: 147a4af0ceeSJacob Faibussowitsch . device - The PetscDevice to configure 148a4af0ceeSJacob Faibussowitsch 149a4af0ceeSJacob Faibussowitsch Notes: 150a4af0ceeSJacob Faibussowitsch The user should not assume that this is a cheap operation 151a4af0ceeSJacob Faibussowitsch 152a4af0ceeSJacob Faibussowitsch Level: beginner 153a4af0ceeSJacob Faibussowitsch 154a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceCreate(), PetscDeviceView(), PetscDeviceDestroy() 155a4af0ceeSJacob Faibussowitsch @*/ 156a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceConfigure(PetscDevice device) 157030f984aSJacob Faibussowitsch { 158030f984aSJacob Faibussowitsch PetscErrorCode ierr; 159030f984aSJacob Faibussowitsch 160030f984aSJacob Faibussowitsch PetscFunctionBegin; 161a4af0ceeSJacob Faibussowitsch PetscValidDevice(device,1); 162a4af0ceeSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 163a4af0ceeSJacob Faibussowitsch /* if no available configuration is available, this cascades all the way down to default 164a4af0ceeSJacob Faibussowitsch and error */ 165a4af0ceeSJacob Faibussowitsch switch (device->type) { 166a4af0ceeSJacob Faibussowitsch case PETSC_DEVICE_CUDA: if (PetscDefined(HAVE_CUDA)) break; 167a4af0ceeSJacob Faibussowitsch case PETSC_DEVICE_HIP: if (PetscDefined(HAVE_HIP)) break; 168a4af0ceeSJacob Faibussowitsch default: 169a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_DEFAULT_CASE(PETSC_COMM_SELF,device->type); 170a4af0ceeSJacob Faibussowitsch break; 171a4af0ceeSJacob Faibussowitsch } 172a4af0ceeSJacob Faibussowitsch } 173a4af0ceeSJacob Faibussowitsch ierr = (*device->ops->configure)(device);CHKERRQ(ierr); 174a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 175a4af0ceeSJacob Faibussowitsch } 176a4af0ceeSJacob Faibussowitsch 177a4af0ceeSJacob Faibussowitsch /*@C 178a4af0ceeSJacob Faibussowitsch PetscDeviceView - View a PetscDevice 179a4af0ceeSJacob Faibussowitsch 180a4af0ceeSJacob Faibussowitsch Collective on viewer, Asynchronous 181a4af0ceeSJacob Faibussowitsch 182a4af0ceeSJacob Faibussowitsch Input Parameter: 183a4af0ceeSJacob Faibussowitsch + device - The PetscDevice to configure 184a4af0ceeSJacob Faibussowitsch - viewer - The PetscViewer to view the device with (NULL for PETSC_VIEWER_STDOUT_WORLD) 185a4af0ceeSJacob Faibussowitsch 186a4af0ceeSJacob Faibussowitsch Level: beginner 187a4af0ceeSJacob Faibussowitsch 188a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceCreate(), PetscDeviceConfigure(), PetscDeviceDestroy() 189a4af0ceeSJacob Faibussowitsch @*/ 190a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceView(PetscDevice device, PetscViewer viewer) 191a4af0ceeSJacob Faibussowitsch { 192a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 193a4af0ceeSJacob Faibussowitsch 194a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 195a4af0ceeSJacob Faibussowitsch PetscValidDevice(device,1); 196a4af0ceeSJacob Faibussowitsch if (!viewer) {ierr = PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer);CHKERRQ(ierr);} 197a4af0ceeSJacob Faibussowitsch PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 198a4af0ceeSJacob Faibussowitsch ierr = (*device->ops->view)(device,viewer);CHKERRQ(ierr); 199a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 200a4af0ceeSJacob Faibussowitsch } 201a4af0ceeSJacob Faibussowitsch 202a4af0ceeSJacob Faibussowitsch static std::array<bool,PETSC_DEVICE_MAX> initializedDevice = {}; 203a4af0ceeSJacob Faibussowitsch static std::array<PetscDevice,PETSC_DEVICE_MAX> defaultDevices = {}; 204a4af0ceeSJacob Faibussowitsch static_assert(initializedDevice.size() == defaultDevices.size(),""); 205a4af0ceeSJacob Faibussowitsch 206a4af0ceeSJacob Faibussowitsch /*@C 207a4af0ceeSJacob Faibussowitsch PetscDeviceInitialize - Initialize PetscDevice 208a4af0ceeSJacob Faibussowitsch 209a4af0ceeSJacob Faibussowitsch Not Collective, Possibly Synchronous 210a4af0ceeSJacob Faibussowitsch 211a4af0ceeSJacob Faibussowitsch Input Parameter: 212a4af0ceeSJacob Faibussowitsch . type - The PetscDeviceType to initialize 213a4af0ceeSJacob Faibussowitsch 214a4af0ceeSJacob Faibussowitsch Notes: 215a4af0ceeSJacob Faibussowitsch Eagerly initializes the corresponding PetscDeviceType if needed. 216a4af0ceeSJacob Faibussowitsch 217a4af0ceeSJacob Faibussowitsch Level: beginner 218a4af0ceeSJacob Faibussowitsch 219a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceInitType, PetscDeviceInitialized(), PetscDeviceCreate(), PetscDeviceDestroy() 220a4af0ceeSJacob Faibussowitsch @*/ 221a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceInitialize(PetscDeviceType type) 222a4af0ceeSJacob Faibussowitsch { 223a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 224a4af0ceeSJacob Faibussowitsch 225a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 226a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type,1); 227a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitializeDefaultDevice_Internal(type,PETSC_DECIDE);CHKERRQ(ierr); 228a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 229a4af0ceeSJacob Faibussowitsch } 230a4af0ceeSJacob Faibussowitsch 231a4af0ceeSJacob Faibussowitsch /*@C 232a4af0ceeSJacob Faibussowitsch PetscDeviceInitialized - Determines whether PetscDevice is initialized for a particular 233a4af0ceeSJacob Faibussowitsch PetscDeviceType 234a4af0ceeSJacob Faibussowitsch 235a4af0ceeSJacob Faibussowitsch Not Collective, Asynchronous 236a4af0ceeSJacob Faibussowitsch 237a4af0ceeSJacob Faibussowitsch Input Parameter: 238a4af0ceeSJacob Faibussowitsch . type - The PetscDeviceType to check 239a4af0ceeSJacob Faibussowitsch 240a4af0ceeSJacob Faibussowitsch Output Parameter: 241a4af0ceeSJacob Faibussowitsch . [return value] - PETSC_TRUE if type is initialized, PETSC_FALSE otherwise 242a4af0ceeSJacob Faibussowitsch 243a4af0ceeSJacob Faibussowitsch Notes: 244a4af0ceeSJacob Faibussowitsch If one has not configured PETSc for a particular PetscDeviceType then this routine will 245a4af0ceeSJacob Faibussowitsch return PETSC_FALSE for that PetscDeviceType. 246a4af0ceeSJacob Faibussowitsch 247a4af0ceeSJacob Faibussowitsch Level: beginner 248a4af0ceeSJacob Faibussowitsch 249a4af0ceeSJacob Faibussowitsch .seealso: PetscDevice, PetscDeviceInitType, PetscDeviceInitialize(), PetscDeviceCreate(), PetscDeviceDestroy() 250a4af0ceeSJacob Faibussowitsch @*/ 251a4af0ceeSJacob Faibussowitsch PetscBool PetscDeviceInitialized(PetscDeviceType type) 252a4af0ceeSJacob Faibussowitsch { 253a4af0ceeSJacob Faibussowitsch return static_cast<PetscBool>(PetscDeviceConfiguredFor_Internal(type) && initializedDevice[type]); 254a4af0ceeSJacob Faibussowitsch } 255a4af0ceeSJacob Faibussowitsch 256a4af0ceeSJacob Faibussowitsch /* Actual intialization function; any functions claiming to initialize PetscDevice or 257a4af0ceeSJacob Faibussowitsch * PetscDeviceContext will have to run through this one */ 258a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceInitializeDefaultDevice_Internal(PetscDeviceType type, PetscInt defaultDeviceId) 259a4af0ceeSJacob Faibussowitsch { 260a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 261a4af0ceeSJacob Faibussowitsch 262a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 263a4af0ceeSJacob Faibussowitsch PetscValidDeviceType(type,1); 264a4af0ceeSJacob Faibussowitsch if (PetscLikely(PetscDeviceInitialized(type))) PetscFunctionReturn(0); 265a4af0ceeSJacob Faibussowitsch if (PetscUnlikelyDebug(defaultDevices[type])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MEM,"Trying to overwrite existing default device of type %s",PetscDeviceTypes[type]); 266a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceCreate(type,defaultDeviceId,&defaultDevices[type]);CHKERRQ(ierr); 267a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceConfigure(defaultDevices[type]);CHKERRQ(ierr); 268030f984aSJacob Faibussowitsch /* the default devices are all automatically "referenced" at least once, otherwise the 269a4af0ceeSJacob Faibussowitsch * reference counting is off for them. We could alternatively increase the reference count 270a4af0ceeSJacob Faibussowitsch * when they are retrieved but that is a lot more brittle; what's to stop someone from doing 271a4af0ceeSJacob Faibussowitsch * the following? 272030f984aSJacob Faibussowitsch 273030f984aSJacob Faibussowitsch for (int i = 0; i < 10000; ++i) auto device = PetscDeviceDefault_Internal(); 274030f984aSJacob Faibussowitsch */ 275a4af0ceeSJacob Faibussowitsch initializedDevice[type] = true; 276a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 277a4af0ceeSJacob Faibussowitsch } 278a4af0ceeSJacob Faibussowitsch 279a4af0ceeSJacob Faibussowitsch static PetscErrorCode PetscDeviceInitializeTypeFromOptions_Private(MPI_Comm comm, PetscDeviceType type, PetscInt defaultDeviceId, PetscBool defaultView, PetscDeviceInitType *defaultInitType) 280a4af0ceeSJacob Faibussowitsch { 281a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 282a4af0ceeSJacob Faibussowitsch 283a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 284a4af0ceeSJacob Faibussowitsch if (!PetscDeviceConfiguredFor_Internal(type)) { 285a4af0ceeSJacob Faibussowitsch ierr = PetscInfo1(PETSC_NULLPTR,"PetscDeviceType %s not supported\n",PetscDeviceTypes[type]);CHKERRQ(ierr); 286a4af0ceeSJacob Faibussowitsch defaultDevices[type] = PETSC_NULLPTR; 287a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 288a4af0ceeSJacob Faibussowitsch } 289a4af0ceeSJacob Faibussowitsch ierr = PetscInfo1(PETSC_NULLPTR,"PetscDeviceType %s supported, initializing\n",PetscDeviceTypes[type]);CHKERRQ(ierr); 290a4af0ceeSJacob Faibussowitsch /* ugly switch needed to pick the right global variable... could maybe do this as a union? */ 291a4af0ceeSJacob Faibussowitsch switch (type) { 292a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_CASE_IF_PETSC_DEFINED(CUDA,initialize,comm,&defaultDeviceId,defaultInitType); 293a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_CASE_IF_PETSC_DEFINED(HIP,initialize,comm,&defaultDeviceId,defaultInitType); 294a4af0ceeSJacob Faibussowitsch default: 295a4af0ceeSJacob Faibussowitsch PETSC_DEVICE_DEFAULT_CASE(comm,type); 296a4af0ceeSJacob Faibussowitsch break; 297a4af0ceeSJacob Faibussowitsch } 298a4af0ceeSJacob Faibussowitsch /* defaultInitType and defaultDeviceId now represent what the individual TYPES have decided 299a4af0ceeSJacob Faibussowitsch * to initialize as */ 300a4af0ceeSJacob Faibussowitsch if (*defaultInitType == PETSC_DEVICE_INIT_EAGER) { 301a4af0ceeSJacob Faibussowitsch ierr = PetscInfo1(PETSC_NULLPTR,"Greedily initializing %s PetscDevice\n",PetscDeviceTypes[type]);CHKERRQ(ierr); 302a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitializeDefaultDevice_Internal(type,defaultDeviceId);CHKERRQ(ierr); 303a4af0ceeSJacob Faibussowitsch if (defaultView) { 304a4af0ceeSJacob Faibussowitsch PetscViewer vwr; 305a4af0ceeSJacob Faibussowitsch 306a4af0ceeSJacob Faibussowitsch ierr = PetscViewerASCIIGetStdout(comm,&vwr);CHKERRQ(ierr); 307a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceView(defaultDevices[type],vwr);CHKERRQ(ierr); 308a4af0ceeSJacob Faibussowitsch } 309030f984aSJacob Faibussowitsch } 310030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 311030f984aSJacob Faibussowitsch } 312030f984aSJacob Faibussowitsch 313030f984aSJacob Faibussowitsch /* called from PetscFinalize() do not call yourself! */ 314a4af0ceeSJacob Faibussowitsch static PetscErrorCode PetscDeviceFinalize_Private(void) 315030f984aSJacob Faibussowitsch { 316030f984aSJacob Faibussowitsch PetscErrorCode ierr; 317030f984aSJacob Faibussowitsch 318030f984aSJacob Faibussowitsch PetscFunctionBegin; 319a4af0ceeSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 320a4af0ceeSJacob Faibussowitsch const auto PetscDeviceCheckAllDestroyedAfterFinalize = [](){ 321a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 322a4af0ceeSJacob Faibussowitsch for (const auto &device : defaultDevices) { 323*3ca90d2dSJacob Faibussowitsch if (PetscUnlikely(device)) SETERRQ2(PETSC_COMM_WORLD,PETSC_ERR_COR,"Device of type '%s' had reference count %" PetscInt_FMT " and was not fully destroyed during PetscFinalize()",PetscDeviceTypes[device->type],device->refcnt); 324a4af0ceeSJacob Faibussowitsch } 325a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 326a4af0ceeSJacob Faibussowitsch }; 327a4af0ceeSJacob Faibussowitsch /* you might be thinking, why on earth are you registered yet another finalizer in a 328a4af0ceeSJacob Faibussowitsch * function already called during PetscRegisterFinalizeAll()? If this seems stupid it's 329a4af0ceeSJacob Faibussowitsch * because it is. 330a4af0ceeSJacob Faibussowitsch * 331a4af0ceeSJacob Faibussowitsch * The crux of the problem is that the initializer (and therefore the ~finalizer~) of 332a4af0ceeSJacob Faibussowitsch * PetscDeviceContext is guaranteed to run after this finalizer. So if the global context 333a4af0ceeSJacob Faibussowitsch * had a default PetscDevice attached it will hold a reference this routine won't destroy 334a4af0ceeSJacob Faibussowitsch * it. So we need to check that all devices have been destroyed after the global context is 335a4af0ceeSJacob Faibussowitsch * destroyed. In summary: 336a4af0ceeSJacob Faibussowitsch * 337a4af0ceeSJacob Faibussowitsch * 1. This finalizer runs and destroys all devices, except it may not because the global 338a4af0ceeSJacob Faibussowitsch * context may still hold a reference! 339a4af0ceeSJacob Faibussowitsch * 2. The global context finalizer runs and in turn actually destroys the referenced 340a4af0ceeSJacob Faibussowitsch * device. 341a4af0ceeSJacob Faibussowitsch * 3. Our newly added finalizer runs and checks that all is well. 342a4af0ceeSJacob Faibussowitsch */ 343a4af0ceeSJacob Faibussowitsch ierr = PetscRegisterFinalize(PetscDeviceCheckAllDestroyedAfterFinalize);CHKERRQ(ierr); 344a4af0ceeSJacob Faibussowitsch } 345a4af0ceeSJacob Faibussowitsch for (auto &&device : defaultDevices) {ierr = PetscDeviceDestroy(&device);CHKERRQ(ierr);} 346a4af0ceeSJacob Faibussowitsch CHKERRCXX(initializedDevice.fill(false)); 347030f984aSJacob Faibussowitsch PetscFunctionReturn(0); 348030f984aSJacob Faibussowitsch } 349030f984aSJacob Faibussowitsch 350a4af0ceeSJacob Faibussowitsch /* begins the init proceeedings for the entire PetscDevice stack. there are 3 stages of 351a4af0ceeSJacob Faibussowitsch * initialization types: 352a4af0ceeSJacob Faibussowitsch 1. defaultInitType - how does PetscDevice as a whole expect to initialize? 353a4af0ceeSJacob Faibussowitsch 2. subTypeDefaultInitType - how does each PetscDevice implementation expect to initialize? 354a4af0ceeSJacob Faibussowitsch e.g. you may want to blanket disable PetscDevice init (and disable say Kokkos init), but 355a4af0ceeSJacob Faibussowitsch have all CUDA devices still initialize. 356a4af0ceeSJacob Faibussowitsch 357a4af0ceeSJacob Faibussowitsch All told the following happens: 358a4af0ceeSJacob Faibussowitsch 0. defaultInitType -> LAZY 359a4af0ceeSJacob Faibussowitsch 1. Check for log_view/log_summary, if yes defaultInitType -> EAGER 360a4af0ceeSJacob Faibussowitsch 2. PetscDevice initializes each sub type with deviceDefaultInitType. 361a4af0ceeSJacob Faibussowitsch 2.1 Each enabled PetscDevice sub-type then does the above disable or view check in addition 362a4af0ceeSJacob Faibussowitsch to checking for specific device init. if view or specific device init 363a4af0ceeSJacob Faibussowitsch subTypeDefaultInitType -> EAGER. disabled once again overrides all. 364a4af0ceeSJacob Faibussowitsch */ 365a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceInitializeFromOptions_Internal(MPI_Comm comm) 366030f984aSJacob Faibussowitsch { 367a4af0ceeSJacob Faibussowitsch PetscBool flg,defaultView = PETSC_FALSE,initializeDeviceContextEagerly = PETSC_FALSE; 368a4af0ceeSJacob Faibussowitsch PetscInt defaultDevice = PETSC_DECIDE; 369a4af0ceeSJacob Faibussowitsch PetscDeviceType deviceContextInitDevice = PETSC_DEVICE_DEFAULT; 370a4af0ceeSJacob Faibussowitsch PetscDeviceInitType defaultInitType; 371a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 372a4af0ceeSJacob Faibussowitsch 373a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 374a4af0ceeSJacob Faibussowitsch if (PetscDefined(USE_DEBUG)) { 375a4af0ceeSJacob Faibussowitsch int result; 376a4af0ceeSJacob Faibussowitsch 377a4af0ceeSJacob Faibussowitsch ierr = MPI_Comm_compare(comm,PETSC_COMM_WORLD,&result);CHKERRMPI(ierr); 378a4af0ceeSJacob Faibussowitsch /* in order to accurately assign ranks to gpus we need to get the MPI_Comm_rank of the 379a4af0ceeSJacob Faibussowitsch * global space */ 380a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(result != MPI_IDENT)) { 381a4af0ceeSJacob Faibussowitsch char name[MPI_MAX_OBJECT_NAME] = {}; 382a4af0ceeSJacob Faibussowitsch int len; /* unused */ 383a4af0ceeSJacob Faibussowitsch 384a4af0ceeSJacob Faibussowitsch ierr = MPI_Comm_get_name(comm,name,&len);CHKERRMPI(ierr); 385a4af0ceeSJacob Faibussowitsch SETERRQ1(comm,PETSC_ERR_MPI,"Default devices being initialized on MPI_Comm '%s' not PETSC_COMM_WORLD",name); 386a4af0ceeSJacob Faibussowitsch } 387a4af0ceeSJacob Faibussowitsch } 388a4af0ceeSJacob Faibussowitsch comm = PETSC_COMM_WORLD; /* from this point on we assume we're on PETSC_COMM_WORLD */ 389a4af0ceeSJacob Faibussowitsch ierr = PetscRegisterFinalize(PetscDeviceFinalize_Private);CHKERRQ(ierr); 390a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsHasName(PETSC_NULLPTR,PETSC_NULLPTR,"-log_view",&flg);CHKERRQ(ierr); 391a4af0ceeSJacob Faibussowitsch if (!flg) { 392a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsHasName(PETSC_NULLPTR,PETSC_NULLPTR,"-log_summary",&flg);CHKERRQ(ierr); 393a4af0ceeSJacob Faibussowitsch } 394a4af0ceeSJacob Faibussowitsch { 395a4af0ceeSJacob Faibussowitsch PetscInt initIdx = flg ? PETSC_DEVICE_INIT_EAGER : PETSC_DEVICE_INIT_LAZY; 396a4af0ceeSJacob Faibussowitsch 397a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsBegin(comm,PETSC_NULLPTR,"PetscDevice Options","Sys");CHKERRQ(ierr); 398a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsEList("-device_enable","How (or whether) to initialize PetscDevices","PetscDeviceInitializeFromOptions_Internal()",PetscDeviceInitTypes,3,PetscDeviceInitTypes[initIdx],&initIdx,PETSC_NULLPTR);CHKERRQ(ierr); 399a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsRangeInt("-device_select","Which device to use. Pass " PetscStringize(PETSC_DECIDE) " to have PETSc decide or (given they exist) [0-NUM_DEVICE) for a specific device","PetscDeviceCreate",defaultDevice,&defaultDevice,PETSC_NULLPTR,PETSC_DECIDE,std::numeric_limits<int>::max());CHKERRQ(ierr); 400a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsBool("-device_view","Display device information and assignments (forces eager initialization)",PETSC_NULLPTR,defaultView,&defaultView,&flg);CHKERRQ(ierr); 401a4af0ceeSJacob Faibussowitsch ierr = PetscOptionsEnd();CHKERRQ(ierr); 402a4af0ceeSJacob Faibussowitsch if (initIdx == PETSC_DEVICE_INIT_NONE) { 403a4af0ceeSJacob Faibussowitsch /* disabled all device initialization if devices are globally disabled */ 404a4af0ceeSJacob Faibussowitsch if (PetscUnlikely(defaultDevice != PETSC_DECIDE)) SETERRQ(comm,PETSC_ERR_USER_INPUT,"You have disabled devices but also specified a particular device to use, these options are mutually exlusive"); 405a4af0ceeSJacob Faibussowitsch defaultView = PETSC_FALSE; 406a4af0ceeSJacob Faibussowitsch } else { 407a4af0ceeSJacob Faibussowitsch defaultView = static_cast<decltype(defaultView)>(defaultView && flg); 408a4af0ceeSJacob Faibussowitsch if (defaultView) initIdx = PETSC_DEVICE_INIT_EAGER; 409a4af0ceeSJacob Faibussowitsch } 410a4af0ceeSJacob Faibussowitsch defaultInitType = static_cast<decltype(defaultInitType)>(initIdx); 411a4af0ceeSJacob Faibussowitsch } 412a4af0ceeSJacob Faibussowitsch static_assert((PETSC_DEVICE_INVALID == 0) && (PETSC_DEVICE_MAX < std::numeric_limits<int>::max()),""); 413a4af0ceeSJacob Faibussowitsch for (int i = 1; i < PETSC_DEVICE_MAX; ++i) { 414a4af0ceeSJacob Faibussowitsch const auto deviceType = static_cast<PetscDeviceType>(i); 415a4af0ceeSJacob Faibussowitsch auto initType = defaultInitType; 416a4af0ceeSJacob Faibussowitsch 417a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitializeTypeFromOptions_Private(comm,deviceType,defaultDevice,defaultView,&initType);CHKERRQ(ierr); 418a4af0ceeSJacob Faibussowitsch if (PetscDeviceConfiguredFor_Internal(deviceType) && (initType == PETSC_DEVICE_INIT_EAGER)) { 419a4af0ceeSJacob Faibussowitsch initializeDeviceContextEagerly = PETSC_TRUE; 420a4af0ceeSJacob Faibussowitsch deviceContextInitDevice = deviceType; 421a4af0ceeSJacob Faibussowitsch } 422a4af0ceeSJacob Faibussowitsch } 423a4af0ceeSJacob Faibussowitsch if (initializeDeviceContextEagerly) { 424a4af0ceeSJacob Faibussowitsch PetscDeviceContext dctx; 425a4af0ceeSJacob Faibussowitsch 426a4af0ceeSJacob Faibussowitsch /* somewhat inefficient here as the device context is potentially fully set up twice (once 427a4af0ceeSJacob Faibussowitsch * when retrieved then the second time if setfromoptions makes changes) */ 428a4af0ceeSJacob Faibussowitsch ierr = PetscInfo1(PETSC_NULLPTR,"Eagerly initializing PetscDeviceContext with %s device\n",PetscDeviceTypes[deviceContextInitDevice]);CHKERRQ(ierr); 429a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetRootDeviceType_Internal(deviceContextInitDevice);CHKERRQ(ierr); 430a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextGetCurrentContext(&dctx);CHKERRQ(ierr); 431a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetFromOptions(comm,"root_",dctx);CHKERRQ(ierr); 432a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceContextSetUp(dctx);CHKERRQ(ierr); 433a4af0ceeSJacob Faibussowitsch } 434a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 435a4af0ceeSJacob Faibussowitsch } 436a4af0ceeSJacob Faibussowitsch 437a4af0ceeSJacob Faibussowitsch /* Get the default PetscDevice for a particular type and constructs them if lazily initialized. */ 438a4af0ceeSJacob Faibussowitsch PetscErrorCode PetscDeviceGetDefaultForType_Internal(PetscDeviceType type, PetscDevice *device) 439a4af0ceeSJacob Faibussowitsch { 440a4af0ceeSJacob Faibussowitsch PetscErrorCode ierr; 441a4af0ceeSJacob Faibussowitsch 442a4af0ceeSJacob Faibussowitsch PetscFunctionBegin; 443a4af0ceeSJacob Faibussowitsch PetscValidPointer(device,2); 444a4af0ceeSJacob Faibussowitsch ierr = PetscDeviceInitialize(type);CHKERRQ(ierr); 445a4af0ceeSJacob Faibussowitsch *device = defaultDevices[type]; 446a4af0ceeSJacob Faibussowitsch PetscFunctionReturn(0); 447030f984aSJacob Faibussowitsch } 448