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