ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
SYCLUtils.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 // Contains code from:
9 // https://github.com/intel/llvm/blob/sycl/sycl/tools/sycl-ls/sycl-ls.cpp
10 // ----------------------------------------------------------------------------
11 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://llvm.org/LICENSE.txt for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 // ----------------------------------------------------------------------------
15 
17 
18 #include <Logging.h>
19 
20 #include <array>
21 #include <cstdlib>
22 #include <sstream>
23 
24 #ifdef BUILD_SYCL_MODULE
25 #include <sycl/sycl.hpp>
26 
28 #endif
29 
30 namespace cloudViewer {
31 namespace core {
32 namespace sy {
33 
34 int SYCLDemo() {
35 #ifdef BUILD_SYCL_MODULE
36  // Ref: https://intel.github.io/llvm-docs/GetStartedGuide.html
37  // Creating buffer of 4 ints to be used inside the kernel code.
38  sycl::buffer<int, 1> buffer(4);
39 
40  // Creating SYCL queue.
41  sycl::queue q;
42 
43  // Size of index space for kernel.
44  sycl::range<1> num_workloads{buffer.size()};
45 
46  // Submitting command group(work) to q.
47  q.submit([&](sycl::handler &cgh) {
48  // Getting write only access to the buffer on a device.
49  auto accessor = buffer.get_access<sycl::access::mode::write>(cgh);
50  // Execute kernel.
51  cgh.parallel_for<class FillBuffer>(
52  num_workloads, [=](sycl::id<1> WIid) {
53  // Fill buffer with indexes.
54  accessor[WIid] = (int)WIid.get(0);
55  });
56  });
57 
58  // Getting access to the buffer on the host.
59  // Implicit barrier waiting for q to complete the work.
60  const auto host_accessor = buffer.get_host_access();
61 
62  // Check the results.
63  bool mismatch_found = false;
64  for (size_t i = 0; i < buffer.size(); ++i) {
65  if (host_accessor[i] != i) {
66  utility::LogInfo("Mismatch found at index {}: expected {}, got {}.",
67  i, i, host_accessor[i]);
68  mismatch_found = true;
69  }
70  }
71 
72  if (mismatch_found) {
73  utility::LogInfo("SYCLDemo failed!");
74  return -1;
75  } else {
76  utility::LogInfo("SYCLDemo passed!");
77  return 0;
78  }
79 #else
80  utility::LogInfo("SYCLDemo is not compiled with BUILD_SYCL_MODULE=ON.");
81  return -1;
82 #endif
83 }
84 
85 #ifdef BUILD_SYCL_MODULE
86 
88  const sycl::device &device) {
89  auto device_type = device.get_info<sycl::info::device::device_type>();
90  switch (device_type) {
91  case sycl::info::device_type::cpu:
92  return "cpu";
93  case sycl::info::device_type::gpu:
94  return "gpu";
95  case sycl::info::device_type::host:
96  return "host";
97  case sycl::info::device_type::accelerator:
98  return "acc";
99  case sycl::info::device_type::custom:
100  return "custom";
101  default:
102  return "unknown";
103  }
104 }
105 
106 static std::string GetBackendName(const sycl::device &device) {
107  sycl::platform platform = device.get_info<sycl::info::device::platform>();
108  sycl::backend backend = platform.get_backend();
109  std::ostringstream os;
110  os << backend;
111  return os.str();
112 }
113 
114 static std::string SYCLDeviceToString(const sycl::device &device) {
115  std::ostringstream os;
116  os << "[" << GetBackendName(device) << ":" << GetDeviceTypeName(device)
117  << "] " << device.get_info<sycl::info::device::name>();
118  return os.str();
119 }
120 #endif
121 
122 void PrintSYCLDevices(bool print_all) {
123 #ifdef BUILD_SYCL_MODULE
124  const char *filter = std::getenv("ONEAPI_DEVICE_SELECTOR");
125  if (filter) {
127  "ONEAPI_DEVICE_SELECTOR environment variable is set to {}. To "
128  "see the correct device id, please unset "
129  "ONEAPI_DEVICE_SELECTOR.",
130  filter);
131  }
132 
133  int nd = 0;
134  utility::LogInfo("# CloudViewer SYCL device");
135  try {
136  auto dev = sycl::device(sycl::gpu_selector_v);
137  utility::LogInfo("- Device(\"SYCL:{}\"): {}", nd,
138  SYCLDeviceToString(dev));
139  ++nd;
140  } catch (const sycl::exception &e) { // No SYCL GPU available.
141  }
142  try {
143  auto dev = sycl::device(sycl::cpu_selector_v);
144  utility::LogInfo("# CloudViewer SYCL device (CPU fallback)");
145  utility::LogInfo("- Device(\"SYCL:{}\"): {}", nd,
146  SYCLDeviceToString(dev));
147  } catch (const sycl::exception &e) { // No SYCL CPU available.
148  if (nd == 0) utility::LogInfo("- Device(\"SYCL:0\"): N/A");
149  }
150  if (print_all) {
151  utility::LogInfo("# All SYCL devices");
152  const std::vector<sycl::platform> &platforms =
153  sycl::platform::get_platforms();
154  for (const sycl::platform &platform : platforms) {
155  sycl::backend backend = platform.get_backend();
156  const std::vector<sycl::device> &devices = platform.get_devices();
157  for (const sycl::device &device : devices) {
158  utility::LogInfo("- {}", SYCLDeviceToString(device));
159  }
160  }
161 
162  utility::LogInfo("# Default SYCL selectors");
163  try {
164  const sycl::device &device = sycl::device(sycl::default_selector_v);
165  utility::LogInfo("- sycl::default_selector_v : {}",
166  SYCLDeviceToString(device));
167  } catch (const sycl::exception &e) {
168  utility::LogInfo("- sycl::default_selector_v : N/A");
169  }
170  try {
171  const sycl::device &device = sycl::device(sycl::cpu_selector_v);
172  utility::LogInfo("- sycl::cpu_selector_v : {}",
173  SYCLDeviceToString(device));
174  } catch (const sycl::exception &e) {
175  utility::LogInfo("- sycl::cpu_selector_v : N/A");
176  }
177  try {
178  const sycl::device &device = sycl::device(sycl::gpu_selector_v);
179  utility::LogInfo("- sycl::gpu_selector_v : {}",
180  SYCLDeviceToString(device));
181  } catch (const sycl::exception &e) {
182  utility::LogInfo("- sycl::gpu_selector_v : N/A");
183  }
184  try {
185  const sycl::device &device =
186  sycl::device(sycl::accelerator_selector_v);
187  utility::LogInfo("- sycl::accelerator_selector_v: {}",
188  SYCLDeviceToString(device));
189  } catch (const sycl::exception &e) {
190  utility::LogInfo("- sycl::accelerator_selector_v: N/A");
191  }
192  }
193 
194 #else
196  "PrintSYCLDevices is not compiled with BUILD_SYCL_MODULE=ON.");
197 #endif
198 }
199 
200 bool IsAvailable() {
201 #ifdef BUILD_SYCL_MODULE
203 #else
204  return false;
205 #endif
206 }
207 
208 bool IsDeviceAvailable(const Device &device) {
209 #ifdef BUILD_SYCL_MODULE
211 #else
212  return false;
213 #endif
214 }
215 
216 std::string GetDeviceType(const Device &device) {
217 #ifdef BUILD_SYCL_MODULE
218  if (IsDeviceAvailable(device)) {
219  return SYCLContext::GetInstance()
220  .GetDeviceProperties(device)
221  .device_type;
222  } else {
223  return "";
224  }
225 #else
226  return "";
227 #endif
228 }
229 
230 std::vector<Device> GetAvailableSYCLDevices() {
231 #ifdef BUILD_SYCL_MODULE
233 #else
234  return {};
235 #endif
236 }
237 
239 #ifdef BUILD_SYCL_MODULE
240 #if defined(_WIN32)
241  _putenv_s("SYCL_CACHE_PERSISTENT", "1");
242 #else
243  setenv("SYCL_CACHE_PERSISTENT", "1", 1);
244 #endif
245 #else
247  "enablePersistentJITCache is not compiled with "
248  "BUILD_SYCL_MODULE=ON.");
249 #endif
250 }
251 
252 } // namespace sy
253 } // namespace core
254 } // namespace cloudViewer
std::string name
#define CLOUDVIEWER_DLL_LOCAL
Definition: Macro.h:23
SYCL queue manager.
Common SYCL utilities.
bool IsDeviceAvailable(const Device &device)
Returns true if the specified SYCL device is available.
Definition: SYCLContext.cpp:32
static SYCLContext & GetInstance()
Get singleton instance.
Definition: SYCLContext.cpp:25
bool IsAvailable()
Returns true if there is at least one SYCL devices.
Definition: SYCLContext.cpp:30
SYCLDevice GetDeviceProperties(const Device &device)
Get SYCL device properties given an CloudViewer device.
Definition: SYCLContext.h:62
std::vector< Device > GetAvailableSYCLDevices()
Returns a list of all available SYCL devices.
Definition: SYCLContext.cpp:35
#define LogWarning(...)
Definition: Logging.h:72
#define LogInfo(...)
Definition: Logging.h:81
CLOUDVIEWER_DLL_LOCAL std::string GetDeviceTypeName(const sycl::device &device)
void enablePersistentJITCache()
Definition: SYCLUtils.cpp:238
bool IsAvailable()
Returns true if there is at least one SYCL device available.
Definition: SYCLUtils.cpp:200
std::string GetDeviceType(const Device &device)
Definition: SYCLUtils.cpp:216
bool IsDeviceAvailable(const Device &device)
Returns true if the specified SYCL device is available.
Definition: SYCLUtils.cpp:208
std::vector< Device > GetAvailableSYCLDevices()
Return a list of available SYCL devices.
Definition: SYCLUtils.cpp:230
void PrintSYCLDevices(bool print_all)
Definition: SYCLUtils.cpp:122
Generic file read and write utility for python interface.
std::string device_type
cpu, gpu, host, acc, custom, unknown.
Definition: SYCLContext.h:30