-
Notifications
You must be signed in to change notification settings - Fork 801
[SYCL] Implement backend content extension #16633
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 24 commits
464174d
217270c
776a3ed
3080741
12bdf3f
a4f6372
c15a31a
0ba58c7
50018cb
b20f042
2c7b110
b884eec
36f4095
5d4a6bf
273f6df
192cf75
5d7d500
5050a3c
ab765f9
e8be859
fa68a24
74c0772
78e7ae6
b2594e8
5b88761
ccdd15c
e4914b8
21f4a9b
91853e0
70c168a
a43e3b4
cc5189e
7b8458c
ab163f7
247932e
688521d
c1a5ea7
bb5b787
a3f837d
d6a2ca5
d5c214c
587941f
2e38117
4ee145e
3308fac
bc695cf
3b2691f
cf94a3e
743c9a7
97637cf
afe72b8
d1f2644
910ce34
d267155
a9e1e21
2c916f6
16186ba
77eda18
a29db25
248fc93
c666340
4ccce5a
2e4d7f8
9aa2184
6a88f93
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,28 @@ ur_native_handle_t device_image_plain::getNative() const { | |
| return impl->getNative(); | ||
| } | ||
|
|
||
| backend device_image_plain::ext_oneapi_get_backend() const noexcept { | ||
| return impl->get_context().get_backend(); | ||
| } | ||
|
|
||
| std::vector<std::byte> | ||
| device_image_plain::ext_oneapi_get_backend_content() const { | ||
| return std::vector(reinterpret_cast<const std::byte *>( | ||
| impl->get_bin_image_ref()->getRawData().BinaryStart), | ||
| reinterpret_cast<const std::byte *>( | ||
| impl->get_bin_image_ref()->getRawData().BinaryEnd)); | ||
| } | ||
|
|
||
| #ifdef __cpp_lib_span | ||
|
||
| std::span<std::byte> | ||
| device_image_plain::ext_oneapi_get_backend_content_view() const { | ||
| return std::span(reinterpret_cast<const std::byte *>( | ||
| impl->get_bin_image_ref()->getRawData().BinaryStart), | ||
| reinterpret_cast<const std::byte *>( | ||
| impl->get_bin_image_ref()->getRawData().BinaryEnd)); | ||
| } | ||
| #endif | ||
|
|
||
| //////////////////////////// | ||
| ///// kernel_bundle_plain | ||
| /////////////////////////// | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| // REQUIRES: level_zero, level_zero_dev_kit, aspect-usm_shared_allocations | ||
| // RUN: %{build} %level_zero_options -fno-sycl-dead-args-optimization -o %t.out | ||
| // RUN: %{run} %t.out | ||
| // | ||
| #include <level_zero/ze_api.h> | ||
| #include <sycl/detail/core.hpp> | ||
| #include <sycl/ext/oneapi/backend/level_zero.hpp> | ||
| #include <sycl/ext/oneapi/free_function_queries.hpp> | ||
| #include <sycl/usm.hpp> | ||
| #include <vector> | ||
|
|
||
| namespace syclext = sycl::ext::oneapi; | ||
| namespace syclexp = sycl::ext::oneapi::experimental; | ||
|
|
||
| extern "C" SYCL_EXT_ONEAPI_FUNCTION_PROPERTY( | ||
| (syclexp::nd_range_kernel<1>)) void iota(int *ptr) { | ||
| size_t id = syclext::this_work_item::get_nd_item<1>().get_global_linear_id(); | ||
| ptr[id] = 42; | ||
| } | ||
|
|
||
| int main() { | ||
| sycl::device d([](const sycl::device &d) { | ||
| return d.get_backend() == sycl::backend::ext_oneapi_level_zero; | ||
steffenlarsen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| }); | ||
| sycl::queue q{d}; | ||
| sycl::context ctxt = q.get_context(); | ||
|
|
||
| // The following ifndef is required due to a number of limitations of free | ||
| // function kernels. See CMPLRLLVM-61498. | ||
| // TODO: Remove it once these limitations are no longer there. | ||
| #ifndef __SYCL_DEVICE_ONLY__ | ||
| // First, run the kernel using the SYCL API. | ||
| auto Bundle = sycl::get_kernel_bundle<sycl::bundle_state::executable>(ctxt); | ||
steffenlarsen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| sycl::kernel_id iota_id = syclexp::get_kernel_id<iota>(); | ||
| sycl::kernel k_iota = Bundle.get_kernel(iota_id); | ||
| int *ptr = sycl::malloc_shared<int>(1, q); | ||
| *ptr = 0; | ||
| q.submit([&](sycl::handler &cgh) { | ||
| cgh.set_args(ptr); | ||
| cgh.parallel_for(sycl::nd_range{{1}, {1}}, k_iota); | ||
| }).wait(); | ||
|
|
||
| // Now, run the kernel by first getting its image as an executable, | ||
| // making an L0 kernel out of it and then making a SYCL kernel out of | ||
| // the L0 kernel. Run this kernel on the SYCL API and verify | ||
| // that it has the same result as the kernel that was run directly on SYCL | ||
| // API. First, get a kernel bundle that contains the kernel "iota". | ||
| auto exe_bndl = sycl::get_kernel_bundle<sycl::bundle_state::executable>( | ||
| ctxt, {d}, | ||
| [&](const sycl::device_image<sycl::bundle_state::executable> &img) { | ||
| return img.has_kernel(iota_id, d); | ||
| }); | ||
| assert(!exe_bndl.empty()); | ||
| std::vector<std::byte> bytes; | ||
| const sycl::device_image<sycl::bundle_state::executable> &img = | ||
| *(exe_bndl.begin()); | ||
| bytes = img.ext_oneapi_get_backend_content(); | ||
|
|
||
| auto ZeContext = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(ctxt); | ||
| auto ZeDevice = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(d); | ||
|
|
||
| ze_result_t status; | ||
| ze_module_desc_t moduleDesc = { | ||
| ZE_STRUCTURE_TYPE_MODULE_DESC, | ||
| nullptr, | ||
| ZE_MODULE_FORMAT_IL_SPIRV, | ||
| bytes.size(), | ||
| reinterpret_cast<unsigned char *>(bytes.data()), | ||
| nullptr, | ||
| nullptr}; | ||
| ze_module_handle_t ZeModule; | ||
| status = zeModuleCreate(ZeContext, ZeDevice, &moduleDesc, &ZeModule, nullptr); | ||
| assert(status == ZE_RESULT_SUCCESS); | ||
|
|
||
| ze_kernel_desc_t kernelDesc = {ZE_STRUCTURE_TYPE_KERNEL_DESC, nullptr, 0, | ||
| "__sycl_kernel_iota"}; | ||
| ze_kernel_handle_t ZeKernel; | ||
| status = zeKernelCreate(ZeModule, &kernelDesc, &ZeKernel); | ||
| assert(status == ZE_RESULT_SUCCESS); | ||
| sycl::kernel k_iota_twin = | ||
| sycl::make_kernel<sycl::backend::ext_oneapi_level_zero>( | ||
| {sycl::make_kernel_bundle<sycl::backend::ext_oneapi_level_zero, | ||
| sycl::bundle_state::executable>({ZeModule}, | ||
| ctxt), | ||
| ZeKernel}, | ||
| ctxt); | ||
| int *ptr_twin = sycl::malloc_shared<int>(1, q); | ||
| *ptr_twin = 1; | ||
| q.submit([&](sycl::handler &cgh) { | ||
| cgh.set_args(ptr_twin); | ||
| cgh.parallel_for(sycl::nd_range{{1}, {1}}, k_iota_twin); | ||
| }).wait(); | ||
| assert(*ptr_twin == *ptr); | ||
| sycl::free(ptr, q); | ||
| sycl::free(ptr_twin, q); | ||
| #endif | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| // RUN: %{build} -fsyntax-only -DTEST_API_VIOLATION=1 -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning | ||
lbushi25 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // RUN: %{build} -o %t.out | ||
| // RUN: %{run} %t.out | ||
|
|
||
| #ifdef __cpp_lib_span | ||
| #include <span> | ||
| #endif | ||
| #include <sycl/detail/core.hpp> | ||
| #include <sycl/kernel_bundle.hpp> | ||
| #include <type_traits> | ||
|
|
||
| class kernel; | ||
|
|
||
| void define_kernel(sycl::queue &q) { | ||
| int data; | ||
| sycl::buffer<int> data_buf(&data, 1); | ||
| q.submit([&](sycl::handler &cgh) { | ||
| sycl::accessor data_acc(data_buf, cgh); | ||
| cgh.parallel_for<class kernel>( | ||
| sycl::nd_range{{1}, {1}}, | ||
| [=](sycl::nd_item<> it) { data_acc[0] = 42; }); | ||
| }); | ||
| } | ||
|
|
||
| int main() { | ||
| sycl::device d; | ||
| sycl::queue q{d}; | ||
| sycl::context ctxt = q.get_context(); | ||
| sycl::kernel_id id = sycl::get_kernel_id<kernel>(); | ||
| auto bundle = | ||
| sycl::get_kernel_bundle<sycl::bundle_state::executable>(ctxt, {id}); | ||
| assert(!bundle.empty()); | ||
| sycl::backend backend; | ||
| std::vector<std::byte> bytes; | ||
| #ifdef __cpp_lib_span | ||
| std::span<std::byte> bytes_view; | ||
| #endif | ||
| for (const auto &img : bundle) { | ||
| // Check that all 3 functions of the api return correct types and compile. | ||
| // Furthermore, check that the backend corresponds to the backend of the | ||
| // bundle Check that the view of the content is indeed equal to the | ||
| // content. | ||
| static_assert(std::is_same_v<decltype(img.ext_oneapi_get_backend()), | ||
| decltype(backend)>); | ||
| static_assert(std::is_same_v<decltype(img.ext_oneapi_get_backend_content()), | ||
| decltype(bytes)>); | ||
| backend = img.ext_oneapi_get_backend(); | ||
| assert(backend == bundle.get_backend()); | ||
| bytes = img.ext_oneapi_get_backend_content(); | ||
| #ifdef __cpp_lib_span | ||
| static_assert( | ||
| std ::is_same_v<decltype(img.ext_oneapi.get_backend_content_view()), | ||
| decltype(bytes_view)>); | ||
| bytes_view = img.ext_oneapi_get_backend_content_view(); | ||
| assert(bytes_view.size() == bytes.size()); | ||
| for (size_t i = 0; i < bytes.size(); ++i) { | ||
| assert(bytes[i] == bytes_view[i]); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| #ifdef TEST_API_VIOLATION | ||
| // Check that the ext_oneapi_get_backend_content and the | ||
| // ext_oneapi_get_backend_content_view of the content functions are not | ||
| // available | ||
| // when the image is not in the executable state. | ||
|
|
||
| auto input_bundle = | ||
| sycl::get_kernel_bundle<sycl::bundle_state::input>(ctxt, {id}); | ||
| // expected-error@+1 {{no matching member function for call to 'ext_oneapi_get_backend_content'}} | ||
| bytes = (*input_bundle.begin()).ext_oneapi_get_backend_content(); | ||
| #ifdef _cpp_lib_span | ||
| // expected-error@+1 {{no matching member function for call to 'ext_oneapi_get_backend_content_view'}} | ||
| bytes_view = (*input_bundle.begin()).ext_oneapi_get_backend_content_view(); | ||
| #endif // __cpp_lib_span | ||
| #endif // TEST_API_VIOLATION | ||
| return 0; | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.