Blender  V3.3
device/hip/device.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #include "device/hip/device.h"
5 
6 #include "util/log.h"
7 
8 #ifdef WITH_HIP
9 # include "device/device.h"
10 # include "device/hip/device_impl.h"
11 
12 # include "util/string.h"
13 # include "util/windows.h"
14 #endif /* WITH_HIP */
15 
17 
19 {
20 #if !defined(WITH_HIP)
21  return false;
22 #elif defined(WITH_HIP_DYNLOAD)
23  static bool initialized = false;
24  static bool result = false;
25 
26  if (initialized)
27  return result;
28 
29  initialized = true;
30  int hipew_result = hipewInit(HIPEW_INIT_HIP);
31  if (hipew_result == HIPEW_SUCCESS) {
32  VLOG_INFO << "HIPEW initialization succeeded";
33  if (HIPDevice::have_precompiled_kernels()) {
34  VLOG_INFO << "Found precompiled kernels";
35  result = true;
36  }
37  else if (hipewCompilerPath() != NULL) {
38  VLOG_INFO << "Found HIPCC " << hipewCompilerPath();
39  result = true;
40  }
41  else {
42  VLOG_INFO << "Neither precompiled kernels nor HIPCC was found,"
43  << " unable to use HIP";
44  }
45  }
46  else {
47  if (hipew_result == HIPEW_ERROR_ATEXIT_FAILED) {
48  VLOG_WARNING << "HIPEW initialization failed: Error setting up atexit() handler";
49  }
50  else if (hipew_result == HIPEW_ERROR_OLD_DRIVER) {
52  << "HIPEW initialization failed: Driver version too old, requires AMD Radeon Pro "
53  "21.Q4 driver or newer";
54  }
55  else {
56  VLOG_WARNING << "HIPEW initialization failed: Error opening HIP dynamic library";
57  }
58  }
59 
60  return result;
61 #else /* WITH_HIP_DYNLOAD */
62  return true;
63 #endif /* WITH_HIP_DYNLOAD */
64 }
65 
66 Device *device_hip_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
67 {
68 #ifdef WITH_HIP
69  return new HIPDevice(info, stats, profiler);
70 #else
71  (void)info;
72  (void)stats;
73  (void)profiler;
74 
75  LOG(FATAL) << "Request to create HIP device without compiled-in support. Should never happen.";
76 
77  return nullptr;
78 #endif
79 }
80 
81 #ifdef WITH_HIP
82 static hipError_t device_hip_safe_init()
83 {
84 # ifdef _WIN32
85  __try {
86  return hipInit(0);
87  }
88  __except (EXCEPTION_EXECUTE_HANDLER) {
89  /* Ignore crashes inside the HIP driver and hope we can
90  * survive even with corrupted HIP installs. */
91  fprintf(stderr, "Cycles HIP: driver crashed, continuing without HIP.\n");
92  }
93 
94  return hipErrorNoDevice;
95 # else
96  return hipInit(0);
97 # endif
98 }
99 #endif /* WITH_HIP */
100 
102 {
103 #ifdef WITH_HIP
104  hipError_t result = device_hip_safe_init();
105  if (result != hipSuccess) {
106  if (result != hipErrorNoDevice)
107  fprintf(stderr, "HIP hipInit: %s\n", hipewErrorString(result));
108  return;
109  }
110 
111  int count = 0;
112  result = hipGetDeviceCount(&count);
113  if (result != hipSuccess) {
114  fprintf(stderr, "HIP hipGetDeviceCount: %s\n", hipewErrorString(result));
115  return;
116  }
117 
118  vector<DeviceInfo> display_devices;
119 
120  for (int num = 0; num < count; num++) {
121  char name[256];
122 
123  result = hipDeviceGetName(name, 256, num);
124  if (result != hipSuccess) {
125  fprintf(stderr, "HIP :hipDeviceGetName: %s\n", hipewErrorString(result));
126  continue;
127  }
128 
129  if (!hipSupportsDevice(num)) {
130  continue;
131  }
132 
133  DeviceInfo info;
134 
135  info.type = DEVICE_HIP;
136  info.description = string(name);
137  info.num = num;
138 
139  info.has_nanovdb = true;
140  info.denoisers = 0;
141 
142  info.has_gpu_queue = true;
143  /* Check if the device has P2P access to any other device in the system. */
144  for (int peer_num = 0; peer_num < count && !info.has_peer_memory; peer_num++) {
145  if (num != peer_num) {
146  int can_access = 0;
147  hipDeviceCanAccessPeer(&can_access, num, peer_num);
148  info.has_peer_memory = (can_access != 0);
149  }
150  }
151 
152  int pci_location[3] = {0, 0, 0};
153  hipDeviceGetAttribute(&pci_location[0], hipDeviceAttributePciDomainID, num);
154  hipDeviceGetAttribute(&pci_location[1], hipDeviceAttributePciBusId, num);
155  hipDeviceGetAttribute(&pci_location[2], hipDeviceAttributePciDeviceId, num);
156  info.id = string_printf("HIP_%s_%04x:%02x:%02x",
157  name,
158  (unsigned int)pci_location[0],
159  (unsigned int)pci_location[1],
160  (unsigned int)pci_location[2]);
161 
162  /* If device has a kernel timeout and no compute preemption, we assume
163  * it is connected to a display and will freeze the display while doing
164  * computations. */
165  int timeout_attr = 0, preempt_attr = 0;
166  hipDeviceGetAttribute(&timeout_attr, hipDeviceAttributeKernelExecTimeout, num);
167 
168  if (timeout_attr && !preempt_attr) {
169  VLOG_INFO << "Device is recognized as display.";
170  info.description += " (Display)";
171  info.display_device = true;
172  display_devices.push_back(info);
173  }
174  else {
175  VLOG_INFO << "Device has compute preemption or is not used for display.";
176  devices.push_back(info);
177  }
178  VLOG_INFO << "Added device \"" << name << "\" with id \"" << info.id << "\".";
179  }
180 
181  if (!display_devices.empty())
182  devices.insert(devices.end(), display_devices.begin(), display_devices.end());
183 #else /* WITH_HIP */
184  (void)devices;
185 #endif /* WITH_HIP */
186 }
187 
189 {
190 #ifdef WITH_HIP
191  hipError_t result = device_hip_safe_init();
192  if (result != hipSuccess) {
193  if (result != hipErrorNoDevice) {
194  return string("Error initializing HIP: ") + hipewErrorString(result);
195  }
196  return "No HIP device found\n";
197  }
198 
199  int count;
200  result = hipGetDeviceCount(&count);
201  if (result != hipSuccess) {
202  return string("Error getting devices: ") + hipewErrorString(result);
203  }
204 
205  string capabilities = "";
206  for (int num = 0; num < count; num++) {
207  char name[256];
208  if (hipDeviceGetName(name, 256, num) != hipSuccess) {
209  continue;
210  }
211  capabilities += string("\t") + name + "\n";
212  int value;
213 # define GET_ATTR(attr) \
214  { \
215  if (hipDeviceGetAttribute(&value, hipDeviceAttribute##attr, num) == hipSuccess) { \
216  capabilities += string_printf("\t\thipDeviceAttribute" #attr "\t\t\t%d\n", value); \
217  } \
218  } \
219  (void)0
220  /* TODO(sergey): Strip all attributes which are not useful for us
221  * or does not depend on the driver.
222  */
223  GET_ATTR(MaxThreadsPerBlock);
224  GET_ATTR(MaxBlockDimX);
225  GET_ATTR(MaxBlockDimY);
226  GET_ATTR(MaxBlockDimZ);
227  GET_ATTR(MaxGridDimX);
228  GET_ATTR(MaxGridDimY);
229  GET_ATTR(MaxGridDimZ);
230  GET_ATTR(MaxSharedMemoryPerBlock);
231  GET_ATTR(TotalConstantMemory);
232  GET_ATTR(WarpSize);
233  GET_ATTR(MaxPitch);
234  GET_ATTR(MaxRegistersPerBlock);
235  GET_ATTR(ClockRate);
236  GET_ATTR(TextureAlignment);
237  GET_ATTR(MultiprocessorCount);
238  GET_ATTR(KernelExecTimeout);
239  GET_ATTR(Integrated);
240  GET_ATTR(CanMapHostMemory);
241  GET_ATTR(ComputeMode);
242  GET_ATTR(MaxTexture1DWidth);
243  GET_ATTR(MaxTexture2DWidth);
244  GET_ATTR(MaxTexture2DHeight);
245  GET_ATTR(MaxTexture3DWidth);
246  GET_ATTR(MaxTexture3DHeight);
247  GET_ATTR(MaxTexture3DDepth);
248  GET_ATTR(ConcurrentKernels);
249  GET_ATTR(EccEnabled);
250  GET_ATTR(MemoryClockRate);
251  GET_ATTR(MemoryBusWidth);
252  GET_ATTR(L2CacheSize);
253  GET_ATTR(MaxThreadsPerMultiProcessor);
254  GET_ATTR(ComputeCapabilityMajor);
255  GET_ATTR(ComputeCapabilityMinor);
256  GET_ATTR(MaxSharedMemoryPerMultiprocessor);
257  GET_ATTR(ManagedMemory);
258  GET_ATTR(IsMultiGpuBoard);
259 # undef GET_ATTR
260  capabilities += "\n";
261  }
262 
263  return capabilities;
264 
265 #else /* WITH_HIP */
266  return "";
267 #endif /* WITH_HIP */
268 }
269 
DenoiserTypeMask denoisers
Definition: device/device.h:73
bool display_device
Definition: device/device.h:66
bool has_peer_memory
Definition: device/device.h:70
bool has_nanovdb
Definition: device/device.h:67
bool has_gpu_queue
Definition: device/device.h:71
DeviceType type
Definition: device/device.h:62
string description
Definition: device/device.h:63
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
@ DEVICE_HIP
Definition: device/device.h:42
void device_hip_info(vector< DeviceInfo > &devices)
Device * device_hip_create(const DeviceInfo &info, Stats &stats, Profiler &profiler)
string device_hip_capabilities()
CCL_NAMESPACE_BEGIN bool device_hip_init()
SyclQueue void void size_t num_bytes void
static bool initialized
Definition: gpu_init_exit.c:22
int count
#define VLOG_INFO
Definition: log.h:77
#define VLOG_WARNING
Definition: log.h:75
#define LOG(severity)
Definition: log.h:36
Vector< CPUDevice > devices
list of all CPUDevices. for every hardware thread an instance of CPUDevice is created
CCL_NAMESPACE_BEGIN string string_printf(const char *format,...)
Definition: string.cpp:22