xref: /petsc/src/sys/objects/device/interface/device.cxx (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
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