.. index:: pair: example; sycl_interop_buffer.cpp .. _doxid-sycl_interop_buffer_8cpp-example: sycl_interop_buffer.cpp ======================= Annotated version: :ref:`Getting started on both CPU and GPU with SYCL extensions API ` Annotated version: :ref:`Getting started on both CPU and GPU with SYCL extensions API ` .. ref-code-block:: cpp /******************************************************************************* * Copyright 2019-2023 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ // [Prologue] #include "example_utils.hpp" #include "oneapi/dnnl/dnnl.hpp" #include "oneapi/dnnl/dnnl_debug.h" #include "oneapi/dnnl/dnnl_sycl.hpp" #if __has_include() #include #elif __has_include() #include #else #error "Unsupported compiler" #endif #include #include #include using namespace :ref:`dnnl `; using namespace :ref:`sycl `; // [Prologue] class kernel_tag; void sycl_interop_buffer_tutorial(:ref:`engine::kind ` engine_kind) { // [Initialize engine] :ref:`engine ` eng(engine_kind, 0); // [Initialize engine] // [Initialize stream] :ref:`dnnl::stream ` strm(eng); // [Initialize stream] // [memory alloc] :ref:`memory::dims ` tz_dims = {2, 3, 4, 5}; const size_t N = std::accumulate(tz_dims.begin(), tz_dims.end(), (size_t)1, std::multiplies()); :ref:`memory::desc ` mem_d( tz_dims, :ref:`memory::data_type::f32 `, :ref:`memory::format_tag::nchw `); :ref:`memory ` mem = :ref:`sycl_interop::make_memory `( mem_d, eng, :ref:`sycl_interop::memory_kind::buffer `); // [memory alloc] // [get sycl buf] auto sycl_buf = sycl_interop::get_buffer(mem); // [get sycl buf] // [sycl kernel exec] queue q = :ref:`sycl_interop::get_queue `(strm); q.submit([&](handler &cgh) { auto a = sycl_buf.get_access(cgh); cgh.parallel_for(range<1>(N), [=](id<1> i) { int idx = (int)i[0]; a[idx] = (idx % 2) ? -idx : idx; }); }); // [sycl kernel exec] // [relu creation] auto relu_pd = :ref:`eltwise_forward::primitive_desc `(eng, :ref:`prop_kind::forward `, :ref:`algorithm::eltwise_relu `, mem_d, mem_d, 0.0f); auto relu = :ref:`eltwise_forward `(relu_pd); // [relu creation] // [relu exec] relu.execute(strm, {{:ref:`DNNL_ARG_SRC `, mem}, {:ref:`DNNL_ARG_DST `, mem}}); strm.wait(); // [relu exec] // [Check the results] auto host_acc = sycl_buf.get_host_access(); for (size_t i = 0; i < N; i++) { float exp_value = (i % 2) ? 0.0f : i; if (host_acc[i] != (float)exp_value) throw std::string( "Unexpected output, find a negative value after the ReLU " "execution."); } // [Check the results] } // [Main] int main(int argc, char **argv) { int exit_code = 0; :ref:`engine::kind ` engine_kind = parse_engine_kind(argc, argv); try { sycl_interop_buffer_tutorial(engine_kind); } catch (:ref:`dnnl::error ` &e) { std::cout << "oneDNN error caught: " << std::endl << "\tStatus: " << dnnl_status2str(e.status) << std::endl << "\tMessage: " << e.:ref:`what `() << std::endl; exit_code = 1; } catch (std::string &e) { std::cout << "Error in the example: " << e << "." << std::endl; exit_code = 2; } catch (exception &e) { std::cout << "Error in the example: " << e.what() << "." << std::endl; exit_code = 3; } std::cout << "Example " << (exit_code ? "failed" : "passed") << " on " << engine_kind2str_upper(engine_kind) << "." << std::endl; finalize(); return exit_code; } // [Main]