xref: /libCEED/rust/libceed-sys/c-src/backends/sycl/ceed-sycl-common.sycl.cpp (revision dd64fc8452c2d35c954858232143719e6bb2e61d)
1bd882c8aSJames Wright // Copyright (c) 2017-2022, 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 
11bd882c8aSJames Wright #include <string>
12bd882c8aSJames Wright #include <sycl/sycl.hpp>
13bd882c8aSJames Wright 
14bd882c8aSJames Wright //------------------------------------------------------------------------------
15bd882c8aSJames Wright // Device information backend init
16bd882c8aSJames Wright //------------------------------------------------------------------------------
17eb7e6cafSJeremy L Thompson int CeedInit_Sycl(Ceed ceed, const char *resource) {
18*dd64fc84SJeremy L Thompson   Ceed_Sycl  *data;
19bd882c8aSJames Wright   const char *device_spec = std::strstr(resource, ":device_id=");
20bd882c8aSJames Wright   const int   device_id   = (device_spec) ? atoi(device_spec + 11) : 0;
21bd882c8aSJames Wright 
22bd882c8aSJames Wright   sycl::info::device_type device_type;
23bd882c8aSJames Wright   if (std::strstr(resource, "/gpu/sycl")) {
24bd882c8aSJames Wright     device_type = sycl::info::device_type::gpu;
25bd882c8aSJames Wright   } else if (std::strstr(resource, "/cpu/sycl")) {
26bd882c8aSJames Wright     device_type = sycl::info::device_type::cpu;
27bd882c8aSJames Wright   } else {
28bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Unsupported SYCL device type requested");
29bd882c8aSJames Wright   }
30bd882c8aSJames Wright 
31bd882c8aSJames Wright   auto sycl_devices = sycl::device::get_devices(device_type);
32bd882c8aSJames Wright   int  device_count = sycl_devices.size();
33bd882c8aSJames Wright 
34bd882c8aSJames Wright   if (0 == device_count) {
35bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "No SYCL devices of the requested type are available");
36bd882c8aSJames Wright   }
37bd882c8aSJames Wright 
38bd882c8aSJames Wright   // Validate the requested device_id
39bd882c8aSJames Wright   if (device_count < device_id + 1) {
40bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND, "Invalid SYCL device id requested");
41bd882c8aSJames Wright   }
42bd882c8aSJames Wright 
43bd882c8aSJames Wright   sycl::device sycl_device{sycl_devices[device_id]};
44bd882c8aSJames Wright   // Check that the device supports explicit device allocations
45bd882c8aSJames Wright   if (!sycl_device.has(sycl::aspect::usm_device_allocations)) {
46bd882c8aSJames Wright     return CeedError(ceed, CEED_ERROR_BACKEND,
47bd882c8aSJames Wright                      "The requested SYCL device does not support explicit "
48bd882c8aSJames Wright                      "device allocations.");
49bd882c8aSJames Wright   }
50bd882c8aSJames Wright 
51bd882c8aSJames Wright   // Creating an asynchronous error handler
52bd882c8aSJames Wright   sycl::async_handler sycl_async_handler = [&](sycl::exception_list exceptionList) {
53bd882c8aSJames Wright     for (std::exception_ptr const &e : exceptionList) {
54bd882c8aSJames Wright       try {
55bd882c8aSJames Wright         std::rethrow_exception(e);
56bd882c8aSJames Wright       } catch (sycl::exception const &e) {
57bd882c8aSJames Wright         std::ostringstream error_msg;
58bd882c8aSJames Wright         error_msg << "SYCL asynchronous exception caught:\n";
59bd882c8aSJames Wright         error_msg << e.what() << std::endl;
60bd882c8aSJames Wright         return CeedError(ceed, CEED_ERROR_BACKEND, error_msg.str().c_str());
61bd882c8aSJames Wright       }
62bd882c8aSJames Wright     }
63bd882c8aSJames Wright     return CEED_ERROR_SUCCESS;
64bd882c8aSJames Wright   };
65bd882c8aSJames Wright 
66bd882c8aSJames Wright   sycl::context sycl_context{sycl_device.get_platform().get_devices()};
67bd882c8aSJames Wright   sycl::queue   sycl_queue{sycl_context, sycl_device, sycl_async_handler};
68bd882c8aSJames Wright 
69bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
70bd882c8aSJames Wright 
71bd882c8aSJames Wright   data->sycl_device  = sycl_device;
72bd882c8aSJames Wright   data->sycl_context = sycl_context;
73bd882c8aSJames Wright   data->sycl_queue   = sycl_queue;
74bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
75bd882c8aSJames Wright }
76bd882c8aSJames Wright 
77bd882c8aSJames Wright //------------------------------------------------------------------------------
78bd882c8aSJames Wright // Backend destroy
79bd882c8aSJames Wright //------------------------------------------------------------------------------
80bd882c8aSJames Wright int CeedDestroy_Sycl(Ceed ceed) {
81bd882c8aSJames Wright   Ceed_Sycl *data;
82*dd64fc84SJeremy L Thompson 
83bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
84bd882c8aSJames Wright   CeedCallBackend(CeedFree(&data));
85bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
86bd882c8aSJames Wright }
87bd882c8aSJames Wright 
88bd882c8aSJames Wright //------------------------------------------------------------------------------
89bd882c8aSJames Wright // Use an external queue
90bd882c8aSJames Wright //------------------------------------------------------------------------------
915ae360d4SJeremy L Thompson int CeedSetStream_Sycl(Ceed ceed, void *handle) {
92*dd64fc84SJeremy L Thompson   Ceed       ceed_delegate = NULL, ceed_fallback = NULL;
93bd882c8aSJames Wright   Ceed_Sycl *data;
94*dd64fc84SJeremy L Thompson 
95bd882c8aSJames Wright   CeedCallBackend(CeedGetData(ceed, &data));
96bd882c8aSJames Wright 
976ca0f394SUmesh Unnikrishnan   CeedCheck(handle, ceed, CEED_ERROR_BACKEND, "Stream handle is null");
98bd882c8aSJames Wright   sycl::queue *q = static_cast<sycl::queue *>(handle);
99bd882c8aSJames Wright 
100bd882c8aSJames Wright   // Ensure we are using the expected device
1015ae360d4SJeremy L Thompson   CeedCheck(data->sycl_device == q->get_device(), ceed, CEED_ERROR_BACKEND, "Device mismatch between provided queue and ceed object");
102bd882c8aSJames Wright   data->sycl_device  = q->get_device();
103bd882c8aSJames Wright   data->sycl_context = q->get_context();
104bd882c8aSJames Wright   data->sycl_queue   = *q;
105bd882c8aSJames Wright 
106bd882c8aSJames Wright   // Revisit this when we have a hierarchy of delegates
107bd882c8aSJames Wright   CeedCallBackend(CeedGetDelegate(ceed, &ceed_delegate));
108bd882c8aSJames Wright   if (ceed_delegate) {
109bd882c8aSJames Wright     Ceed_Sycl *delegate_data;
110*dd64fc84SJeremy L Thompson 
111bd882c8aSJames Wright     CeedCallBackend(CeedGetData(ceed_delegate, &delegate_data));
112bd882c8aSJames Wright     delegate_data->sycl_device  = q->get_device();
113bd882c8aSJames Wright     delegate_data->sycl_context = q->get_context();
114bd882c8aSJames Wright     delegate_data->sycl_queue   = *q;
115bd882c8aSJames Wright   }
116bd882c8aSJames Wright 
1176ca0f394SUmesh Unnikrishnan   // Set queue and context for Ceed Fallback object
1186ca0f394SUmesh Unnikrishnan   CeedGetOperatorFallbackCeed(ceed, &ceed_fallback);
1196ca0f394SUmesh Unnikrishnan   if (ceed_fallback) {
1206ca0f394SUmesh Unnikrishnan     Ceed_Sycl *fallback_data;
121*dd64fc84SJeremy L Thompson 
1226ca0f394SUmesh Unnikrishnan     CeedCallBackend(CeedGetData(ceed_fallback, &fallback_data));
1236ca0f394SUmesh Unnikrishnan     fallback_data->sycl_device  = q->get_device();
1246ca0f394SUmesh Unnikrishnan     fallback_data->sycl_context = q->get_context();
1256ca0f394SUmesh Unnikrishnan     fallback_data->sycl_queue   = *q;
1266ca0f394SUmesh Unnikrishnan   }
127bd882c8aSJames Wright   return CEED_ERROR_SUCCESS;
128bd882c8aSJames Wright }
129bd882c8aSJames Wright 
130bd882c8aSJames Wright //------------------------------------------------------------------------------
131