oneAPI Deep Neural Network Library (oneDNN)
Performance library for Deep Learning
2.3.0
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 
49 static 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 
67 static 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 
88 static 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
95 static 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) {
127  dnnl_stream_t s;
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
160 static 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) {
192  dnnl_stream_t s;
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:2262
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:2268
@ dnnl_cpu
CPU engine.
Definition: dnnl_types.h:2266
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:2752
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:2717
An opaque structure to describe an engine.
Memory descriptor.
Definition: dnnl_types.h:1557
An opaque structure to describe a memory.
An opaque structure to describe an execution stream.