oneAPI Deep Neural Network Library (oneDNN)
Performance library for Deep Learning
2.1.3
dnnl_sycl.hpp
1/*******************************************************************************
2* Copyright 2020 Intel Corporation
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*******************************************************************************/
16
17#ifndef ONEAPI_DNNL_DNNL_SYCL_HPP
18#define ONEAPI_DNNL_DNNL_SYCL_HPP
19
21#include <algorithm>
22#include <cstdlib>
23#include <iterator>
24#include <memory>
25#include <string>
26#include <vector>
27#include <unordered_map>
28
29#include <CL/sycl.hpp>
30
31#include "oneapi/dnnl/dnnl.hpp"
32#include "oneapi/dnnl/dnnl_sycl.h"
34
37
38namespace dnnl {
39
42
48
50namespace sycl_interop {
51
53enum class memory_kind {
58};
59
65 return static_cast<dnnl_sycl_interop_memory_kind_t>(akind);
66}
67
75 const cl::sycl::device &adevice, const cl::sycl::context &acontext) {
76 dnnl_engine_t aengine;
78 static_cast<const void *>(&adevice),
79 static_cast<const void *>(&acontext)),
80 "could not create an engine");
81 return engine(aengine);
82}
83
89inline cl::sycl::context get_context(const engine &aengine) {
90 void *ctx_ptr;
92 dnnl_sycl_interop_engine_get_context(aengine.get(), &ctx_ptr),
93 "could not get a context handle");
94 auto ctx = *static_cast<cl::sycl::context *>(ctx_ptr);
95 return ctx;
96}
97
103inline cl::sycl::device get_device(const engine &aengine) {
104 void *dev_ptr;
106 dnnl_sycl_interop_engine_get_device(aengine.get(), &dev_ptr),
107 "could not get a device handle");
108 auto dev = *static_cast<cl::sycl::device *>(dev_ptr);
109 return dev;
110}
111
119inline stream make_stream(const engine &aengine, cl::sycl::queue &aqueue) {
120 dnnl_stream_t astream;
122 dnnl_sycl_interop_stream_create(&astream, aengine.get(), &aqueue),
123 "could not create a stream");
124 return stream(astream);
125}
126
132inline cl::sycl::queue get_queue(const stream &astream) {
133 void *queue_ptr;
135 dnnl_sycl_interop_stream_get_queue(astream.get(), &queue_ptr),
136 "could not get a stream handle");
137 auto queue = *static_cast<cl::sycl::queue *>(queue_ptr);
138 return queue;
139}
140
151template <typename T, int ndims = 1>
152cl::sycl::buffer<T, ndims> get_buffer(const memory &amemory) {
153 static_assert(ndims == 1, "only 1D buffers supported");
154
155 void *handle_ptr;
156 error::wrap_c_api(dnnl_memory_get_data_handle(amemory.get(), &handle_ptr),
157 "could not get SYCL buffer object");
158
159 // XXX: workaround: zero-range buffer cannot be constructed.
160 if (!handle_ptr) return cl::sycl::buffer<T, ndims>(cl::sycl::range<1>(1));
161
162 auto &buf_u8 = *static_cast<cl::sycl::buffer<uint8_t, 1> *>(handle_ptr);
163 auto range = cl::sycl::range<1>(buf_u8.get_size() / sizeof(T));
164 return buf_u8.reinterpret<T, 1>(range);
165}
166
173template <typename T, int ndims>
174void set_buffer(memory &amemory, cl::sycl::buffer<T, ndims> &abuffer) {
175 auto range = cl::sycl::range<1>(abuffer.get_size());
176 auto buf_u8 = abuffer.template reinterpret<uint8_t, 1>(range);
178 static_cast<void *>(&buf_u8), nullptr),
179 "could not set SYCL buffer object");
180}
181
189template <typename T, int ndims>
190void set_buffer(memory &amemory, cl::sycl::buffer<T, ndims> &abuffer,
191 const stream &astream) {
192 auto range = cl::sycl::range<1>(abuffer.get_size());
193 auto buf_u8 = abuffer.template reinterpret<uint8_t, 1>(range);
195 static_cast<void *>(&buf_u8), astream.get(true)),
196 "could not set SYCL buffer object");
197}
198
204inline memory_kind get_memory_kind(const memory &amemory) {
208 "could not get memory kind");
209 return static_cast<memory_kind>(ckind);
210}
211
240inline memory make_memory(const memory::desc &memory_desc,
241 const engine &aengine, memory_kind kind,
243 dnnl_memory_t c_memory;
245 dnnl_sycl_interop_memory_create(&c_memory, &memory_desc.data,
246 aengine.get(), convert_to_c(kind), handle),
247 "could not create a memory");
248 return memory(c_memory);
249}
250
258template <typename T, int ndims = 1>
259memory make_memory(const memory::desc &memory_desc, const engine &aengine,
260 cl::sycl::buffer<T, ndims> &abuffer) {
261 memory amemory(memory_desc, aengine, DNNL_MEMORY_NONE);
262 set_buffer(amemory, abuffer);
263 return amemory;
264}
265
283inline cl::sycl::event execute(const dnnl::primitive &aprimitive,
284 const stream &astream, const std::unordered_map<int, memory> &args,
285 const std::vector<cl::sycl::event> &deps = {}) {
286 std::vector<dnnl_exec_arg_t> c_args;
287 c_args.reserve(args.size());
288 for (const auto &a : args)
289 c_args.push_back({a.first, a.second.get()});
290
291 cl::sycl::event return_event;
293 dnnl_sycl_interop_primitive_execute(aprimitive.get(), astream.get(),
294 (int)c_args.size(), c_args.data(), &deps, &return_event),
295 "could not execute a primitive");
296 return return_event;
297}
298
299} // namespace sycl_interop
300
302
304
305} // namespace dnnl
306
308
309#endif // DNNL_SYCL_HPP
dnnl_status_t DNNL_API dnnl_memory_get_data_handle(const_dnnl_memory_t memory, void **handle)
Returns memory object's data handle.
#define DNNL_MEMORY_NONE
Special pointer value that indicates that a memory object should not have an underlying buffer.
Definition: dnnl_types.h:1506
#define DNNL_MEMORY_ALLOCATE
Special pointer value that indicates that the library needs to allocate an underlying buffer for a me...
Definition: dnnl_types.h:1510
dnnl_status_t DNNL_API dnnl_sycl_interop_engine_get_context(dnnl_engine_t engine, void **context)
Returns the SYCL context associated with an engine.
dnnl_status_t DNNL_API dnnl_sycl_interop_memory_get_memory_kind(const_dnnl_memory_t memory, dnnl_sycl_interop_memory_kind_t *memory_kind)
Returns the memory allocation kind associated with a memory object.
dnnl_status_t DNNL_API dnnl_sycl_interop_primitive_execute(const_dnnl_primitive_t primitive, dnnl_stream_t stream, int nargs, const dnnl_exec_arg_t *args, const void *deps, void *return_event)
Executes computations specified by the primitive in a specified stream and returns a SYCL event.
dnnl_status_t DNNL_API dnnl_sycl_interop_stream_create(dnnl_stream_t *stream, dnnl_engine_t engine, void *queue)
Creates an execution stream for a given engine associated with a SYCL queue.
dnnl_status_t DNNL_API dnnl_sycl_interop_engine_create(dnnl_engine_t *engine, const void *device, const void *context)
Creates an engine associated with a SYCL device and a SYCL context.
dnnl_sycl_interop_memory_kind_t
Memory allocation kind.
Definition: dnnl_sycl_types.h:34
dnnl_status_t DNNL_API dnnl_sycl_interop_stream_get_queue(dnnl_stream_t stream, void **queue)
Returns the SYCL queue associated with an execution stream.
dnnl_status_t DNNL_API dnnl_sycl_interop_memory_create(dnnl_memory_t *memory, const dnnl_memory_desc_t *memory_desc, dnnl_engine_t engine, dnnl_sycl_interop_memory_kind_t memory_kind, void *handle)
Creates a memory object.
dnnl_status_t DNNL_API dnnl_sycl_interop_engine_get_device(dnnl_engine_t engine, void **device)
Returns the SYCL device associated with an engine.
dnnl_status_t DNNL_API dnnl_sycl_interop_memory_set_buffer(dnnl_memory_t memory, void *buffer, dnnl_stream_t stream)
Sets a SYCL buffer for a memory object.
@ dnnl_sycl_interop_buffer
Buffer memory allocation kind.
Definition: dnnl_sycl_types.h:38
@ dnnl_sycl_interop_usm
USM (device, shared, host, or unknown) memory allocation kind.
Definition: dnnl_sycl_types.h:36
cl::sycl::queue get_queue(const stream &astream)
Returns the SYCL queue associated with an execution stream.
Definition: dnnl_sycl.hpp:132
stream make_stream(const engine &aengine, cl::sycl::queue &aqueue)
Creates an execution stream for a given engine associated with a SYCL queue.
Definition: dnnl_sycl.hpp:119
cl::sycl::context get_context(const engine &aengine)
Returns the SYCL context associated with an engine.
Definition: dnnl_sycl.hpp:89
engine make_engine(const cl::sycl::device &adevice, const cl::sycl::context &acontext)
Constructs an engine from SYCL device and context objects.
Definition: dnnl_sycl.hpp:74
dnnl_sycl_interop_memory_kind_t convert_to_c(memory_kind akind)
Converts a memory allocation kind enum value from C++ API to C API type.
Definition: dnnl_sycl.hpp:64
cl::sycl::buffer< T, ndims > get_buffer(const memory &amemory)
Returns the SYCL buffer associated with a memory object.
Definition: dnnl_sycl.hpp:152
memory_kind get_memory_kind(const memory &amemory)
Returns the memory allocation kind associated with a memory object.
Definition: dnnl_sycl.hpp:204
memory_kind
Memory allocation kind.
Definition: dnnl_sycl.hpp:53
@ buffer
Buffer memory allocation kind.
@ usm
USM (device, shared, host, or unknown) memory allocation kind.
void set_buffer(memory &amemory, cl::sycl::buffer< T, ndims > &abuffer)
Sets SYCL buffer associated with a memory object.
Definition: dnnl_sycl.hpp:174
cl::sycl::device get_device(const engine &aengine)
Returns the SYCL device associated with an engine.
Definition: dnnl_sycl.hpp:103
memory make_memory(const memory::desc &memory_desc, const engine &aengine, memory_kind kind, void *handle=DNNL_MEMORY_ALLOCATE)
Creates a memory object.
Definition: dnnl_sycl.hpp:240
cl::sycl::event execute(const dnnl::primitive &aprimitive, const stream &astream, const std::unordered_map< int, memory > &args, const std::vector< cl::sycl::event > &deps={})
Executes computations specified by the primitive in a specified stream and returns a SYCL event.
Definition: dnnl_sycl.hpp:283
oneDNN namespace
Definition: dnnl.hpp:74
C++ API.
An execution engine.
Definition: dnnl.hpp:869
static void wrap_c_api(dnnl_status_t status, const char *message)
A convenience function for wrapping calls to C API functions.
Definition: dnnl.hpp:103
oneDNN C API handle wrapper class.
Definition: dnnl.hpp:136
T get(bool allow_empty=false) const
Returns the underlying C API handle.
Definition: dnnl.hpp:185
A memory descriptor.
Definition: dnnl.hpp:1984
dnnl_memory_desc_t data
The underlying C API data structure.
Definition: dnnl.hpp:1987
Memory object.
Definition: dnnl.hpp:1108
Base class for all computational primitives.
Definition: dnnl.hpp:269
An execution stream.
Definition: dnnl.hpp:985
An opaque structure to describe an engine.
An opaque structure to describe a memory.
An opaque structure to describe an execution stream.