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