xref: /libCEED/rust/libceed-sys/c-src/backends/sycl/ceed-sycl-common.sycl.cpp (revision bd882c8a454763a096666645dc9a6229d5263694)
1*bd882c8aSJames Wright // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other
2*bd882c8aSJames Wright // CEED contributors. All Rights Reserved. See the top-level LICENSE and NOTICE
3*bd882c8aSJames Wright // files for details.
4*bd882c8aSJames Wright //
5*bd882c8aSJames Wright // SPDX-License-Identifier: BSD-2-Clause
6*bd882c8aSJames Wright //
7*bd882c8aSJames Wright // This file is part of CEED:  http://github.com/ceed
8*bd882c8aSJames Wright 
9*bd882c8aSJames Wright #include "ceed-sycl-common.hpp"
10*bd882c8aSJames Wright 
11*bd882c8aSJames Wright #include <string>
12*bd882c8aSJames Wright #include <sycl/sycl.hpp>
13*bd882c8aSJames Wright 
14*bd882c8aSJames Wright //------------------------------------------------------------------------------
15*bd882c8aSJames Wright // Get root resource without device spec
16*bd882c8aSJames Wright //------------------------------------------------------------------------------
17*bd882c8aSJames Wright int CeedSyclGetResourceRoot(Ceed ceed, const char *resource, char **resource_root) {
18*bd882c8aSJames Wright   const char *device_spec       = std::strstr(resource, ":device_id=");
19*bd882c8aSJames Wright   size_t      resource_root_len = device_spec ? (size_t)(device_spec - resource) + 1 : strlen(resource) + 1;
20*bd882c8aSJames Wright   CeedCallBackend(CeedCalloc(resource_root_len, resource_root));
21*bd882c8aSJames Wright   memcpy(*resource_root, resource, resource_root_len - 1);
22*bd882c8aSJames Wright 
23*bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
24*bd882c8aSJames Wright }
25*bd882c8aSJames Wright 
26*bd882c8aSJames Wright //------------------------------------------------------------------------------
27*bd882c8aSJames Wright // Device information backend init
28*bd882c8aSJames Wright //------------------------------------------------------------------------------
29*bd882c8aSJames Wright int CeedSyclInit(Ceed ceed, const char *resource) {
30*bd882c8aSJames Wright   const char *device_spec = std::strstr(resource, ":device_id=");
31*bd882c8aSJames Wright   const int   device_id   = (device_spec) ? atoi(device_spec + 11) : 0;
32*bd882c8aSJames Wright 
33*bd882c8aSJames Wright   sycl::info::device_type device_type;
34*bd882c8aSJames Wright   if (std::strstr(resource, "/gpu/sycl")) {
35*bd882c8aSJames Wright     device_type = sycl::info::device_type::gpu;
36*bd882c8aSJames Wright   } else if (std::strstr(resource, "/cpu/sycl")) {
37*bd882c8aSJames Wright     device_type = sycl::info::device_type::cpu;
38*bd882c8aSJames Wright   } else {
39*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Unsupported SYCL device type requested");
40*bd882c8aSJames Wright   }
41*bd882c8aSJames Wright 
42*bd882c8aSJames Wright   auto sycl_devices = sycl::device::get_devices(device_type);
43*bd882c8aSJames Wright   int  device_count = sycl_devices.size();
44*bd882c8aSJames Wright 
45*bd882c8aSJames Wright   if (0 == device_count) {
46*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "No SYCL devices of the requested type are available");
47*bd882c8aSJames Wright   }
48*bd882c8aSJames Wright 
49*bd882c8aSJames Wright   // Validate the requested device_id
50*bd882c8aSJames Wright   if (device_count < device_id + 1) {
51*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Invalid SYCL device id requested");
52*bd882c8aSJames Wright   }
53*bd882c8aSJames Wright 
54*bd882c8aSJames Wright   sycl::device sycl_device{sycl_devices[device_id]};
55*bd882c8aSJames Wright   // Check that the device supports explicit device allocations
56*bd882c8aSJames Wright   if (!sycl_device.has(sycl::aspect::usm_device_allocations)) {
57*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND,
58*bd882c8aSJames Wright                      "The requested SYCL device does not support explicit "
59*bd882c8aSJames Wright                      "device allocations.");
60*bd882c8aSJames Wright   }
61*bd882c8aSJames Wright 
62*bd882c8aSJames Wright   // Creating an asynchronous error handler
63*bd882c8aSJames Wright   sycl::async_handler sycl_async_handler = [&](sycl::exception_list exceptionList) {
64*bd882c8aSJames Wright     for (std::exception_ptr const &e : exceptionList) {
65*bd882c8aSJames Wright       try {
66*bd882c8aSJames Wright         std::rethrow_exception(e);
67*bd882c8aSJames Wright       } catch (sycl::exception const &e) {
68*bd882c8aSJames Wright         std::ostringstream error_msg;
69*bd882c8aSJames Wright         error_msg << "SYCL asynchronous exception caught:\n";
70*bd882c8aSJames Wright         error_msg << e.what() << std::endl;
71*bd882c8aSJames Wright         return CeedError(ceed, CEED_ERROR_BACKEND, error_msg.str().c_str());
72*bd882c8aSJames Wright       }
73*bd882c8aSJames Wright     }
74*bd882c8aSJames Wright     return CEED_ERROR_SUCCESS;
75*bd882c8aSJames Wright   };
76*bd882c8aSJames Wright 
77*bd882c8aSJames Wright   sycl::context sycl_context{sycl_device.get_platform().get_devices()};
78*bd882c8aSJames Wright   sycl::queue   sycl_queue{sycl_context, sycl_device, sycl_async_handler};
79*bd882c8aSJames Wright 
80*bd882c8aSJames Wright   Ceed_Sycl *data;
81*bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
82*bd882c8aSJames Wright 
83*bd882c8aSJames Wright   data->sycl_device  = sycl_device;
84*bd882c8aSJames Wright   data->sycl_context = sycl_context;
85*bd882c8aSJames Wright   data->sycl_queue   = sycl_queue;
86*bd882c8aSJames Wright 
87*bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
88*bd882c8aSJames Wright }
89*bd882c8aSJames Wright 
90*bd882c8aSJames Wright //------------------------------------------------------------------------------
91*bd882c8aSJames Wright // Backend destroy
92*bd882c8aSJames Wright //------------------------------------------------------------------------------
93*bd882c8aSJames Wright int CeedDestroy_Sycl(Ceed ceed) {
94*bd882c8aSJames Wright   Ceed_Sycl *data;
95*bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
96*bd882c8aSJames Wright   CeedCallBackend(CeedFree(&data));
97*bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
98*bd882c8aSJames Wright }
99*bd882c8aSJames Wright 
100*bd882c8aSJames Wright //------------------------------------------------------------------------------
101*bd882c8aSJames Wright // Use an external queue
102*bd882c8aSJames Wright //------------------------------------------------------------------------------
103*bd882c8aSJames Wright int CeedSetSyclStream(Ceed ceed, void *handle) {
104*bd882c8aSJames Wright   Ceed_Sycl *data;
105*bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
106*bd882c8aSJames Wright 
107*bd882c8aSJames Wright   if (!handle) {
108*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Stream handle is null");
109*bd882c8aSJames Wright   }
110*bd882c8aSJames Wright   sycl::queue *q = static_cast<sycl::queue *>(handle);
111*bd882c8aSJames Wright 
112*bd882c8aSJames Wright   // Ensure we are using the expected device
113*bd882c8aSJames Wright   if (data->sycl_device != q->get_device()) {
114*bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Device mismatch between provided queue and ceed object");
115*bd882c8aSJames Wright   }
116*bd882c8aSJames Wright   data->sycl_device  = q->get_device();
117*bd882c8aSJames Wright   data->sycl_context = q->get_context();
118*bd882c8aSJames Wright   data->sycl_queue   = *q;
119*bd882c8aSJames Wright 
120*bd882c8aSJames Wright   // Revisit this when we have a hierarchy of delegates
121*bd882c8aSJames Wright   Ceed ceed_delegate = NULL;
122*bd882c8aSJames Wright   CeedCallBackend(CeedGetDelegate(ceed, &ceed_delegate));
123*bd882c8aSJames Wright   if (ceed_delegate) {
124*bd882c8aSJames Wright     Ceed_Sycl *delegate_data;
125*bd882c8aSJames Wright     CeedCallBackend(CeedGetData(ceed_delegate, &delegate_data));
126*bd882c8aSJames Wright     delegate_data->sycl_device  = q->get_device();
127*bd882c8aSJames Wright     delegate_data->sycl_context = q->get_context();
128*bd882c8aSJames Wright     delegate_data->sycl_queue   = *q;
129*bd882c8aSJames Wright   }
130*bd882c8aSJames Wright 
131*bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
132*bd882c8aSJames Wright }
133*bd882c8aSJames Wright 
134*bd882c8aSJames Wright //------------------------------------------------------------------------------
135