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) { 18bd882c8aSJames Wright const char *device_spec = std::strstr(resource, ":device_id="); 19bd882c8aSJames Wright const int device_id = (device_spec) ? atoi(device_spec + 11) : 0; 20bd882c8aSJames Wright 21bd882c8aSJames Wright sycl::info::device_type device_type; 22bd882c8aSJames Wright if (std::strstr(resource, "/gpu/sycl")) { 23bd882c8aSJames Wright device_type = sycl::info::device_type::gpu; 24bd882c8aSJames Wright } else if (std::strstr(resource, "/cpu/sycl")) { 25bd882c8aSJames Wright device_type = sycl::info::device_type::cpu; 26bd882c8aSJames Wright } else { 27bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Unsupported SYCL device type requested"); 28bd882c8aSJames Wright } 29bd882c8aSJames Wright 30bd882c8aSJames Wright auto sycl_devices = sycl::device::get_devices(device_type); 31bd882c8aSJames Wright int device_count = sycl_devices.size(); 32bd882c8aSJames Wright 33bd882c8aSJames Wright if (0 == device_count) { 34bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "No SYCL devices of the requested type are available"); 35bd882c8aSJames Wright } 36bd882c8aSJames Wright 37bd882c8aSJames Wright // Validate the requested device_id 38bd882c8aSJames Wright if (device_count < device_id + 1) { 39bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, "Invalid SYCL device id requested"); 40bd882c8aSJames Wright } 41bd882c8aSJames Wright 42bd882c8aSJames Wright sycl::device sycl_device{sycl_devices[device_id]}; 43bd882c8aSJames Wright // Check that the device supports explicit device allocations 44bd882c8aSJames Wright if (!sycl_device.has(sycl::aspect::usm_device_allocations)) { 45bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, 46bd882c8aSJames Wright "The requested SYCL device does not support explicit " 47bd882c8aSJames Wright "device allocations."); 48bd882c8aSJames Wright } 49bd882c8aSJames Wright 50bd882c8aSJames Wright // Creating an asynchronous error handler 51bd882c8aSJames Wright sycl::async_handler sycl_async_handler = [&](sycl::exception_list exceptionList) { 52bd882c8aSJames Wright for (std::exception_ptr const &e : exceptionList) { 53bd882c8aSJames Wright try { 54bd882c8aSJames Wright std::rethrow_exception(e); 55bd882c8aSJames Wright } catch (sycl::exception const &e) { 56bd882c8aSJames Wright std::ostringstream error_msg; 57bd882c8aSJames Wright error_msg << "SYCL asynchronous exception caught:\n"; 58bd882c8aSJames Wright error_msg << e.what() << std::endl; 59bd882c8aSJames Wright return CeedError(ceed, CEED_ERROR_BACKEND, error_msg.str().c_str()); 60bd882c8aSJames Wright } 61bd882c8aSJames Wright } 62bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 63bd882c8aSJames Wright }; 64bd882c8aSJames Wright 65bd882c8aSJames Wright sycl::context sycl_context{sycl_device.get_platform().get_devices()}; 66bd882c8aSJames Wright sycl::queue sycl_queue{sycl_context, sycl_device, sycl_async_handler}; 67bd882c8aSJames Wright 68bd882c8aSJames Wright Ceed_Sycl *data; 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 75bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 76bd882c8aSJames Wright } 77bd882c8aSJames Wright 78bd882c8aSJames Wright //------------------------------------------------------------------------------ 79bd882c8aSJames Wright // Backend destroy 80bd882c8aSJames Wright //------------------------------------------------------------------------------ 81bd882c8aSJames Wright int CeedDestroy_Sycl(Ceed ceed) { 82bd882c8aSJames Wright Ceed_Sycl *data; 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) { 92bd882c8aSJames Wright Ceed_Sycl *data; 93bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed, &data)); 94bd882c8aSJames Wright 95*6ca0f394SUmesh Unnikrishnan CeedCheck(handle, ceed, CEED_ERROR_BACKEND, "Stream handle is null"); 96bd882c8aSJames Wright sycl::queue *q = static_cast<sycl::queue *>(handle); 97bd882c8aSJames Wright 98bd882c8aSJames Wright // Ensure we are using the expected device 995ae360d4SJeremy L Thompson CeedCheck(data->sycl_device == q->get_device(), ceed, CEED_ERROR_BACKEND, "Device mismatch between provided queue and ceed object"); 100bd882c8aSJames Wright data->sycl_device = q->get_device(); 101bd882c8aSJames Wright data->sycl_context = q->get_context(); 102bd882c8aSJames Wright data->sycl_queue = *q; 103bd882c8aSJames Wright 104bd882c8aSJames Wright // Revisit this when we have a hierarchy of delegates 105bd882c8aSJames Wright Ceed ceed_delegate = NULL; 106bd882c8aSJames Wright CeedCallBackend(CeedGetDelegate(ceed, &ceed_delegate)); 107bd882c8aSJames Wright if (ceed_delegate) { 108bd882c8aSJames Wright Ceed_Sycl *delegate_data; 109bd882c8aSJames Wright CeedCallBackend(CeedGetData(ceed_delegate, &delegate_data)); 110bd882c8aSJames Wright delegate_data->sycl_device = q->get_device(); 111bd882c8aSJames Wright delegate_data->sycl_context = q->get_context(); 112bd882c8aSJames Wright delegate_data->sycl_queue = *q; 113bd882c8aSJames Wright } 114bd882c8aSJames Wright 115*6ca0f394SUmesh Unnikrishnan // Set queue and context for Ceed Fallback object 116*6ca0f394SUmesh Unnikrishnan Ceed ceed_fallback = NULL; 117*6ca0f394SUmesh Unnikrishnan CeedGetOperatorFallbackCeed(ceed, &ceed_fallback); 118*6ca0f394SUmesh Unnikrishnan if (ceed_fallback) { 119*6ca0f394SUmesh Unnikrishnan Ceed_Sycl *fallback_data; 120*6ca0f394SUmesh Unnikrishnan CeedCallBackend(CeedGetData(ceed_fallback, &fallback_data)); 121*6ca0f394SUmesh Unnikrishnan fallback_data->sycl_device = q->get_device(); 122*6ca0f394SUmesh Unnikrishnan fallback_data->sycl_context = q->get_context(); 123*6ca0f394SUmesh Unnikrishnan fallback_data->sycl_queue = *q; 124*6ca0f394SUmesh Unnikrishnan } 125*6ca0f394SUmesh Unnikrishnan 126bd882c8aSJames Wright return CEED_ERROR_SUCCESS; 127bd882c8aSJames Wright } 128bd882c8aSJames Wright 129bd882c8aSJames Wright //------------------------------------------------------------------------------ 130