oneAPI Deep Neural Network Library (oneDNN)
Performance library for Deep Learning
2.1.3
example_utils.h
1/*******************************************************************************
2* Copyright 2019-2021 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 EXAMPLE_UTILS_H
18#define EXAMPLE_UTILS_H
19
20#include <assert.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26#include "dnnl.h"
27#include "dnnl_debug.h"
28
29#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
30#include "dnnl_ocl.h"
31#endif
32
33#define COMPLAIN_DNNL_ERROR_AND_EXIT(what, status) \
34 do { \
35 printf("[%s:%d] `%s` returns oneDNN error: %s.\n", __FILE__, __LINE__, \
36 what, dnnl_status2str(status)); \
37 printf("Example failed.\n"); \
38 exit(1); \
39 } while (0)
40
41#define COMPLAIN_EXAMPLE_ERROR_AND_EXIT(complain_fmt, ...) \
42 do { \
43 printf("[%s:%d] Error in the example: " complain_fmt ".\n", __FILE__, \
44 __LINE__, __VA_ARGS__); \
45 printf("Example failed.\n"); \
46 exit(2); \
47 } while (0)
48
49static dnnl_engine_kind_t validate_engine_kind(dnnl_engine_kind_t akind) {
50 // Checking if a GPU exists on the machine
51 if (akind == dnnl_gpu) {
53 printf("Application couldn't find GPU, please run with CPU "
54 "instead.\n");
55 exit(0);
56 }
57 }
58 return akind;
59}
60
61#define CHECK(f) \
62 do { \
63 dnnl_status_t s_ = f; \
64 if (s_ != dnnl_success) COMPLAIN_DNNL_ERROR_AND_EXIT(#f, s_); \
65 } while (0)
66
67static inline dnnl_engine_kind_t parse_engine_kind(int argc, char **argv) {
68 // Returns default engine kind, i.e. CPU, if none given
69 if (argc == 1) {
70 return validate_engine_kind(dnnl_cpu);
71 } else if (argc == 2) {
72 // Checking the engine type, i.e. CPU or GPU
73 char *engine_kind_str = argv[1];
74 if (!strcmp(engine_kind_str, "cpu")) {
75 return validate_engine_kind(dnnl_cpu);
76 } else if (!strcmp(engine_kind_str, "gpu")) {
77 return validate_engine_kind(dnnl_gpu);
78 }
79 }
80
81 // If all above fails, the example should be run properly
82 COMPLAIN_EXAMPLE_ERROR_AND_EXIT(
83 "inappropriate engine kind.\n"
84 "Please run the example like this: %s [cpu|gpu].",
85 argv[0]);
86}
87
88static inline const char *engine_kind2str_upper(dnnl_engine_kind_t kind) {
89 if (kind == dnnl_cpu) return "CPU";
90 if (kind == dnnl_gpu) return "GPU";
91 return "<Unknown engine>";
92}
93
94// Read from memory, write to handle
95static inline void read_from_dnnl_memory(void *handle, dnnl_memory_t mem) {
96 dnnl_engine_t eng;
97 dnnl_engine_kind_t eng_kind;
98 const dnnl_memory_desc_t *md;
99
100 if (!handle) COMPLAIN_EXAMPLE_ERROR_AND_EXIT("%s", "handle is NULL.");
101
102 CHECK(dnnl_memory_get_engine(mem, &eng));
103 CHECK(dnnl_engine_get_kind(eng, &eng_kind));
104 CHECK(dnnl_memory_get_memory_desc(mem, &md));
105 size_t bytes = dnnl_memory_desc_get_size(md);
106
107#ifdef DNNL_WITH_SYCL
108 bool is_cpu_sycl
109 = (DNNL_CPU_RUNTIME == DNNL_RUNTIME_SYCL && eng_kind == dnnl_cpu);
110 bool is_gpu_sycl
111 = (DNNL_GPU_RUNTIME == DNNL_RUNTIME_SYCL && eng_kind == dnnl_gpu);
112 if (is_cpu_sycl || is_gpu_sycl) {
113 void *mapped_ptr = NULL;
114 CHECK(dnnl_memory_map_data(mem, &mapped_ptr));
115 if (mapped_ptr) {
116 for (size_t i = 0; i < bytes; ++i) {
117 ((char *)handle)[i] = ((char *)mapped_ptr)[i];
118 }
119 }
120 CHECK(dnnl_memory_unmap_data(mem, mapped_ptr));
121 return;
122 }
123#endif
124
125#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
126 if (eng_kind == dnnl_gpu) {
128 cl_command_queue q;
129 cl_mem m;
130
134
135 cl_int ret = clEnqueueReadBuffer(
136 q, m, CL_TRUE, 0, bytes, handle, 0, NULL, NULL);
137 if (ret != CL_SUCCESS)
138 COMPLAIN_EXAMPLE_ERROR_AND_EXIT(
139 "clEnqueueReadBuffer failed (status code: %d)", ret);
140
142 }
143#endif
144
145 if (eng_kind == dnnl_cpu) {
146 void *ptr = NULL;
147 CHECK(dnnl_memory_get_data_handle(mem, &ptr));
148 if (ptr) {
149 for (size_t i = 0; i < bytes; ++i) {
150 ((char *)handle)[i] = ((char *)ptr)[i];
151 }
152 }
153 return;
154 }
155
156 assert(!"not expected");
157}
158
159// Read from handle, write to memory
160static inline void write_to_dnnl_memory(void *handle, dnnl_memory_t mem) {
161 dnnl_engine_t eng;
162 dnnl_engine_kind_t eng_kind;
163 const dnnl_memory_desc_t *md;
164
165 if (!handle) COMPLAIN_EXAMPLE_ERROR_AND_EXIT("%s", "handle is NULL.");
166
167 CHECK(dnnl_memory_get_engine(mem, &eng));
168 CHECK(dnnl_engine_get_kind(eng, &eng_kind));
169 CHECK(dnnl_memory_get_memory_desc(mem, &md));
170 size_t bytes = dnnl_memory_desc_get_size(md);
171
172#ifdef DNNL_WITH_SYCL
173 bool is_cpu_sycl
174 = (DNNL_CPU_RUNTIME == DNNL_RUNTIME_SYCL && eng_kind == dnnl_cpu);
175 bool is_gpu_sycl
176 = (DNNL_GPU_RUNTIME == DNNL_RUNTIME_SYCL && eng_kind == dnnl_gpu);
177 if (is_cpu_sycl || is_gpu_sycl) {
178 void *mapped_ptr = NULL;
179 CHECK(dnnl_memory_map_data(mem, &mapped_ptr));
180 if (mapped_ptr) {
181 for (size_t i = 0; i < bytes; ++i) {
182 ((char *)mapped_ptr)[i] = ((char *)handle)[i];
183 }
184 }
185 CHECK(dnnl_memory_unmap_data(mem, mapped_ptr));
186 return;
187 }
188#endif
189
190#if DNNL_GPU_RUNTIME == DNNL_RUNTIME_OCL
191 if (eng_kind == dnnl_gpu) {
193 cl_command_queue q;
194 cl_mem m;
195
199
200 cl_int ret = clEnqueueWriteBuffer(
201 q, m, CL_TRUE, 0, bytes, handle, 0, NULL, NULL);
202 if (ret != CL_SUCCESS)
203 COMPLAIN_EXAMPLE_ERROR_AND_EXIT(
204 "clEnqueueWriteBuffer failed (status code: %d)", ret);
205
207 return;
208 }
209#endif
210
211 if (eng_kind == dnnl_cpu) {
212 void *ptr = NULL;
213 CHECK(dnnl_memory_get_data_handle(mem, &ptr));
214 if (ptr) {
215 for (size_t i = 0; i < bytes; ++i) {
216 ((char *)ptr)[i] = ((char *)handle)[i];
217 }
218 }
219 return;
220 }
221
222 assert(!"not expected");
223}
224
225#endif
dnnl_engine_kind_t
Kinds of engines.
Definition: dnnl_types.h:2147
dnnl_status_t DNNL_API dnnl_engine_get_kind(dnnl_engine_t engine, dnnl_engine_kind_t *kind)
Returns the kind of an engine.
size_t DNNL_API dnnl_engine_get_count(dnnl_engine_kind_t kind)
Returns the number of engines of a particular kind.
@ dnnl_gpu
GPU engine.
Definition: dnnl_types.h:2153
@ dnnl_cpu
CPU engine.
Definition: dnnl_types.h:2151
dnnl_status_t DNNL_API dnnl_memory_unmap_data(const_dnnl_memory_t memory, void *mapped_ptr)
Unmaps a memory object and writes back any changes made to the previously mapped memory buffer.
dnnl_status_t DNNL_API dnnl_memory_get_engine(const_dnnl_memory_t memory, dnnl_engine_t *engine)
Returns the engine of a memory object.
dnnl_status_t DNNL_API dnnl_memory_get_memory_desc(const_dnnl_memory_t memory, const dnnl_memory_desc_t **memory_desc)
Returns the memory descriptor for a memory object.
dnnl_status_t DNNL_API dnnl_memory_get_data_handle(const_dnnl_memory_t memory, void **handle)
Returns memory object's data handle.
dnnl_status_t DNNL_API dnnl_memory_map_data(const_dnnl_memory_t memory, void **mapped_ptr)
Maps a memory object and returns a host-side pointer to a memory buffer with a copy of its contents.
size_t DNNL_API dnnl_memory_desc_get_size(const dnnl_memory_desc_t *memory_desc)
Returns the size of a memory descriptor.
dnnl_status_t DNNL_API dnnl_ocl_interop_stream_get_command_queue(dnnl_stream_t stream, cl_command_queue *queue)
Returns the OpenCL command queue associated with an execution stream.
dnnl_status_t DNNL_API dnnl_ocl_interop_memory_get_mem_object(const_dnnl_memory_t memory, cl_mem *mem_object)
Returns an OpenCL memory object associated with a memory object.
#define DNNL_RUNTIME_SYCL
SYCL runtime.
Definition: dnnl_types.h:2627
dnnl_status_t DNNL_API dnnl_stream_destroy(dnnl_stream_t stream)
Destroys an execution stream.
dnnl_status_t DNNL_API dnnl_stream_create(dnnl_stream_t *stream, dnnl_engine_t engine, unsigned flags)
Creates an execution stream.
@ dnnl_stream_default_flags
Default stream configuration.
Definition: dnnl_types.h:2592
An opaque structure to describe an engine.
Memory descriptor.
Definition: dnnl_types.h:1445
An opaque structure to describe a memory.
An opaque structure to describe an execution stream.