This C API example demonstrates how to build an AlexNet model training.
The example implements a few layers from AlexNet model.
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "example_utils.h"
#define BATCH 8
#define IC 3
#define OC 96
#define CONV_IH 227
#define CONV_IW 227
#define CONV_OH 55
#define CONV_OW 55
#define CONV_STRIDE 4
#define CONV_PAD 0
#define POOL_OH 27
#define POOL_OW 27
#define POOL_STRIDE 2
#define POOL_PAD 0
static size_t product(
dnnl_dim_t *arr,
size_t size) {
size_t prod = 1;
for (size_t i = 0; i < size; ++i)
prod *= arr[i];
return prod;
}
static void init_net_data(
float *data, uint32_t dim,
const dnnl_dim_t *dims) {
if (dim == 1) {
data[i] = (float)(i % 1637);
}
} else if (dim == 4) {
dnnl_dim_t indx = in * dims[1] * dims[2] * dims[3]
+ ic * dims[2] * dims[3] + ih * dims[3] + iw;
data[indx] = (float)(indx % 1637);
}
}
}
typedef struct {
int nargs;
} args_t;
static void prepare_arg_node(args_t *node, int nargs) {
node->nargs = nargs;
}
static void free_arg_node(args_t *node) {
free(node->args);
}
}
static void init_data_memory(uint32_t dim,
const dnnl_dim_t *dims,
&user_md, dim, dims,
dnnl_f32, user_tag));
write_to_dnnl_memory(data, *memory);
}
int dir_is_user_to_prim,
uint32_t *net_index,
if (dir_is_user_to_prim) {
user_memory_md, user_mem_engine, prim_memory_md,
prim_engine, NULL));
} else {
prim_memory_md, prim_engine, user_memory_md,
user_mem_engine, NULL));
}
net[*net_index] = *reorder;
prepare_arg_node(&net_args[*net_index], 2);
dir_is_user_to_prim ? *user_memory : *prim_memory);
dir_is_user_to_prim ? *prim_memory : *user_memory);
(*net_index)++;
} else {
*prim_memory = NULL;
*reorder = NULL;
}
}
void simple_net() {
uint32_t n_fwd = 0, n_bwd = 0;
args_t net_fwd_args[10], net_bwd_args[10];
dnnl_dim_t net_src_sizes[4] = {BATCH, IC, CONV_IH, CONV_IW};
dnnl_dim_t net_dst_sizes[4] = {BATCH, OC, POOL_OH, POOL_OW};
float *net_src = (float *)malloc(product(net_src_sizes, 4) * sizeof(float));
float *net_dst = (float *)malloc(product(net_dst_sizes, 4) * sizeof(float));
init_net_data(net_src, 4, net_src_sizes);
memset(net_dst, 0, product(net_dst_sizes, 4) * sizeof(float));
dnnl_dim_t conv_user_weights_sizes[4] = {OC, IC, 11, 11};
dnnl_dim_t conv_user_dst_sizes[4] = {BATCH, OC, CONV_OH, CONV_OW};
dnnl_dim_t conv_strides[2] = {CONV_STRIDE, CONV_STRIDE};
dnnl_dim_t conv_padding[2] = {CONV_PAD, CONV_PAD};
float *conv_src = net_src;
float *conv_weights = (float *)malloc(
product(conv_user_weights_sizes, 4) * sizeof(float));
float *conv_bias
= (float *)malloc(product(conv_bias_sizes, 1) * sizeof(float));
init_net_data(conv_weights, 4, conv_user_weights_sizes);
init_net_data(conv_bias, 1, conv_bias_sizes);
conv_user_bias_memory;
init_data_memory(4, conv_user_src_sizes,
dnnl_nchw, engine, conv_src,
&conv_user_src_memory);
init_data_memory(4, conv_user_weights_sizes,
dnnl_oihw, engine,
conv_weights, &conv_user_weights_memory);
init_data_memory(1, conv_bias_sizes,
dnnl_x, engine, conv_bias,
&conv_user_bias_memory);
{
conv_dst_md;
&conv_bias_md, &conv_dst_md, conv_strides, conv_padding,
conv_padding));
&conv_pd, &conv_any_desc, NULL, engine, NULL));
}
dnnl_memory_t conv_internal_src_memory, conv_internal_weights_memory,
conv_internal_dst_memory;
CHECK(prepare_reorder(&conv_user_src_memory, conv_src_md, engine, 1,
&conv_internal_src_memory, &conv_reorder_src, &n_fwd, net_fwd,
net_fwd_args));
CHECK(prepare_reorder(&conv_user_weights_memory, conv_weights_md, engine, 1,
&conv_internal_weights_memory, &conv_reorder_weights, &n_fwd,
net_fwd, net_fwd_args));
? conv_internal_src_memory
: conv_user_src_memory;
? conv_internal_weights_memory
: conv_user_weights_memory;
net_fwd[n_fwd] = conv;
prepare_arg_node(&net_fwd_args[n_fwd], 4);
set_arg(&net_fwd_args[n_fwd].args[0],
DNNL_ARG_SRC, conv_src_memory);
conv_weights_memory);
set_arg(&net_fwd_args[n_fwd].args[2],
DNNL_ARG_BIAS, conv_user_bias_memory);
conv_internal_dst_memory);
n_fwd++;
float negative_slope = 0.0f;
net_fwd[n_fwd] = relu;
prepare_arg_node(&net_fwd_args[n_fwd], 2);
conv_internal_dst_memory);
set_arg(&net_fwd_args[n_fwd].args[1],
DNNL_ARG_DST, relu_dst_memory);
n_fwd++;
uint32_t local_size = 5;
float alpha = 0.0001f;
float beta = 0.75f;
float k = 1.0f;
net_fwd[n_fwd] = lrn;
prepare_arg_node(&net_fwd_args[n_fwd], 3);
set_arg(&net_fwd_args[n_fwd].args[0],
DNNL_ARG_SRC, relu_dst_memory);
set_arg(&net_fwd_args[n_fwd].args[1],
DNNL_ARG_DST, lrn_dst_memory);
n_fwd++;
dnnl_dim_t pool_strides[2] = {POOL_STRIDE, POOL_STRIDE};
dnnl_dim_t pool_padding[2] = {POOL_PAD, POOL_PAD};
init_data_memory(4, pool_dst_sizes,
dnnl_nchw, engine, net_dst,
&pool_user_dst_memory);
{
pool_kernel, pool_dilation, pool_padding, pool_padding));
&pool_pd, &pool_desc, NULL, engine, NULL));
}
n_fwd += 1;
CHECK(prepare_reorder(&pool_user_dst_memory, pool_dst_md, engine, 0,
&pool_internal_dst_memory, &pool_reorder_dst, &n_fwd, net_fwd,
net_fwd_args));
n_fwd -= pool_reorder_dst ? 2 : 1;
? pool_internal_dst_memory
: pool_user_dst_memory;
net_fwd[n_fwd] = pool;
prepare_arg_node(&net_fwd_args[n_fwd], 3);
set_arg(&net_fwd_args[n_fwd].args[0],
DNNL_ARG_SRC, lrn_dst_memory);
set_arg(&net_fwd_args[n_fwd].args[1],
DNNL_ARG_DST, pool_dst_memory);
n_fwd++;
if (pool_reorder_dst) n_fwd += 1;
float *net_diff_dst
= (float *)malloc(product(pool_dst_sizes, 4) * sizeof(float));
init_net_data(net_diff_dst, 4, pool_dst_sizes);
init_data_memory(4, pool_dst_sizes,
dnnl_nchw, engine, net_diff_dst,
&pool_user_diff_dst_memory);
pool_diff_src_md, pool_diff_dst_md, pool_strides, pool_kernel,
pool_dilation, pool_padding, pool_padding));
&pool_bwd_pd, &pool_bwd_desc, NULL, engine, pool_pd));
dnnl_memory_t pool_diff_dst_memory, pool_internal_diff_dst_memory;
CHECK(prepare_reorder(&pool_user_diff_dst_memory, pool_diff_dst_md, engine,
1, &pool_internal_diff_dst_memory, &pool_reorder_diff_dst, &n_bwd,
net_bwd, net_bwd_args));
pool_diff_dst_memory = pool_internal_diff_dst_memory
? pool_internal_diff_dst_memory
: pool_user_diff_dst_memory;
net_bwd[n_bwd] = pool_bwd;
prepare_arg_node(&net_bwd_args[n_bwd], 3);
pool_diff_dst_memory);
pool_diff_src_memory);
n_bwd++;
lrn_diff_dst_md, lrn_src_md, local_size, alpha, beta, k));
&lrn_bwd_pd, &lrn_bwd_desc, NULL, engine, lrn_pd));
net_bwd[n_bwd] = lrn_bwd;
prepare_arg_node(&net_bwd_args[n_bwd], 4);
set_arg(&net_bwd_args[n_bwd].args[0],
DNNL_ARG_SRC, relu_dst_memory);
pool_diff_src_memory);
lrn_diff_src_memory);
n_bwd++;
relu_diff_dst_md, relu_src_md, negative_slope, 0));
&relu_bwd_pd, &relu_bwd_desc, NULL, engine, relu_pd));
net_bwd[n_bwd] = relu_bwd;
prepare_arg_node(&net_bwd_args[n_bwd], 3);
conv_internal_dst_memory);
lrn_diff_src_memory);
relu_diff_src_memory);
n_bwd++;
float *conv_diff_bias_buffer
= (float *)malloc(product(conv_bias_sizes, 1) * sizeof(float));
float *conv_user_diff_weights_buffer = (float *)malloc(
product(conv_user_weights_sizes, 4) * sizeof(float));
init_data_memory(4, conv_user_weights_sizes,
dnnl_oihw, engine,
conv_user_diff_weights_buffer, &conv_user_diff_weights_memory);
{
conv_diff_bias_md, conv_diff_dst_md;
&conv_diff_src_md, &conv_diff_weights_md, &conv_diff_bias_md,
&conv_diff_dst_md, conv_strides, conv_padding, conv_padding));
&conv_bwd_weights_desc, NULL, engine, conv_pd));
}
CHECK(prepare_reorder(&conv_src_memory, conv_diff_src_md, engine, 1,
&conv_bwd_internal_src_memory, &conv_bwd_reorder_src, &n_bwd,
net_bwd, net_bwd_args));
dnnl_memory_t conv_bwd_weights_src_memory = conv_bwd_internal_src_memory
? conv_bwd_internal_src_memory
: conv_src_memory;
CHECK(prepare_reorder(&relu_diff_src_memory, conv_diff_dst_md, engine, 1,
&conv_internal_diff_dst_memory, &conv_reorder_diff_dst, &n_bwd,
net_bwd, net_bwd_args));
dnnl_memory_t conv_diff_dst_memory = conv_internal_diff_dst_memory
? conv_internal_diff_dst_memory
: relu_diff_src_memory;
n_bwd += 1;
CHECK(prepare_reorder(&conv_user_diff_weights_memory, conv_diff_weights_md,
engine, 0, &conv_internal_diff_weights_memory,
&conv_reorder_diff_weights, &n_bwd, net_bwd, net_bwd_args));
n_bwd -= conv_reorder_diff_weights ? 2 : 1;
dnnl_memory_t conv_diff_weights_memory = conv_internal_diff_weights_memory
? conv_internal_diff_weights_memory
: conv_user_diff_weights_memory;
conv_diff_bias_memory, conv_diff_bias_buffer));
net_bwd[n_bwd] = conv_bwd_weights;
prepare_arg_node(&net_bwd_args[n_bwd], 4);
conv_bwd_weights_src_memory);
conv_diff_dst_memory);
conv_diff_weights_memory);
conv_diff_bias_memory);
n_bwd++;
if (conv_reorder_diff_weights) n_bwd += 1;
void *net_diff_weights = NULL;
void *net_diff_bias = NULL;
int n_iter = 10;
for (int i = 0; i < n_iter; i++) {
for (uint32_t i = 0; i < n_fwd; ++i)
net_fwd_args[i].nargs, net_fwd_args[i].args));
void *net_output = NULL;
for (uint32_t i = 0; i < n_bwd; ++i)
net_bwd_args[i].nargs, net_bwd_args[i].args));
conv_user_diff_weights_memory, &net_diff_weights));
conv_diff_bias_memory, &net_diff_bias));
}
for (uint32_t i = 0; i < n_fwd; ++i)
free_arg_node(&net_fwd_args[i]);
for (uint32_t i = 0; i < n_bwd; ++i)
free_arg_node(&net_bwd_args[i]);
free(net_src);
free(net_dst);
free(conv_weights);
free(conv_bias);
free(net_diff_dst);
free(conv_diff_bias_buffer);
free(conv_user_diff_weights_buffer);
}
int main(int argc, char **argv) {
simple_net();
printf("Example passed on CPU.\n");
return 0;
}
dnnl_status_t DNNL_API dnnl_convolution_forward_desc_init(dnnl_convolution_desc_t *conv_desc, dnnl_prop_kind_t prop_kind, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *src_desc, const dnnl_memory_desc_t *weights_desc, const dnnl_memory_desc_t *bias_desc, const dnnl_memory_desc_t *dst_desc, const dnnl_dims_t strides, const dnnl_dims_t padding_l, const dnnl_dims_t padding_r)
Initializes a descriptor for a convolution forward propagation primitive.
dnnl_status_t DNNL_API dnnl_convolution_backward_weights_desc_init(dnnl_convolution_desc_t *conv_desc, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *src_desc, const dnnl_memory_desc_t *diff_weights_desc, const dnnl_memory_desc_t *diff_bias_desc, const dnnl_memory_desc_t *diff_dst_desc, const dnnl_dims_t strides, const dnnl_dims_t padding_l, const dnnl_dims_t padding_r)
Initializes a descriptor for a convolution weights gradient primitive.
dnnl_status_t DNNL_API dnnl_eltwise_forward_desc_init(dnnl_eltwise_desc_t *eltwise_desc, dnnl_prop_kind_t prop_kind, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *data_desc, float alpha, float beta)
Initializes a descriptor for eltwise forward propagation primitive.
dnnl_status_t DNNL_API dnnl_eltwise_backward_desc_init(dnnl_eltwise_desc_t *eltwise_desc, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *diff_data_desc, const dnnl_memory_desc_t *data_desc, float alpha, float beta)
Initializes a descriptor for eltwise backward propagation primitive.
dnnl_status_t DNNL_API dnnl_engine_destroy(dnnl_engine_t engine)
Destroys an engine.
dnnl_status_t DNNL_API dnnl_engine_create(dnnl_engine_t *engine, dnnl_engine_kind_t kind, size_t index)
Creates an engine.
@ dnnl_cpu
CPU engine.
Definition: dnnl_types.h:2151
dnnl_status_t DNNL_API dnnl_lrn_backward_desc_init(dnnl_lrn_desc_t *lrn_desc, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *diff_data_desc, const dnnl_memory_desc_t *data_desc, dnnl_dim_t local_size, float alpha, float beta, float k)
Initializes a descriptor for LRN backward propagation primitive.
dnnl_status_t DNNL_API dnnl_lrn_forward_desc_init(dnnl_lrn_desc_t *lrn_desc, dnnl_prop_kind_t prop_kind, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *data_desc, dnnl_dim_t local_size, float alpha, float beta, float k)
Initializes a descriptor for LRN forward propagation primitive.
dnnl_format_tag_t
Memory format tag specification.
Definition: dnnl_types.h:164
dnnl_status_t DNNL_API dnnl_memory_create(dnnl_memory_t *memory, const dnnl_memory_desc_t *memory_desc, dnnl_engine_t engine, void *handle)
Creates a memory object.
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_set_data_handle(dnnl_memory_t memory, void *handle)
Sets the underlying memory buffer.
dnnl_status_t DNNL_API dnnl_memory_get_data_handle(const_dnnl_memory_t memory, void **handle)
Returns memory object's data handle.
int64_t dnnl_dim_t
A type to describe tensor dimension.
Definition: dnnl_types.h:1333
dnnl_status_t DNNL_API dnnl_memory_destroy(dnnl_memory_t memory)
Destroys a memory object.
int DNNL_API dnnl_memory_desc_equal(const dnnl_memory_desc_t *lhs, const dnnl_memory_desc_t *rhs)
Compares two memory descriptors.
#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_memory_desc_init_by_tag(dnnl_memory_desc_t *memory_desc, int ndims, const dnnl_dims_t dims, dnnl_data_type_t data_type, dnnl_format_tag_t tag)
Initializes a memory descriptor using dimensions and memory format tag.
@ dnnl_f32
32-bit/single-precision floating point.
Definition: dnnl_types.h:70
@ dnnl_oihw
4D CNN weights tensor, an alias to dnnl_abcd
Definition: dnnl_types.h:585
@ dnnl_nchw
4D CNN activations tensor, an alias to dnnl_abcd
Definition: dnnl_types.h:562
@ dnnl_x
1D tensor, an alias to dnnl_a
Definition: dnnl_types.h:548
@ dnnl_format_tag_any
Undefined memory format tag.
Definition: dnnl_types.h:169
dnnl_status_t DNNL_API dnnl_pooling_v2_backward_desc_init(dnnl_pooling_v2_desc_t *pool_desc, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *diff_src_desc, const dnnl_memory_desc_t *diff_dst_desc, const dnnl_dims_t strides, const dnnl_dims_t kernel, const dnnl_dims_t dilation, const dnnl_dims_t padding_l, const dnnl_dims_t padding_r)
Initializes a descriptor for pooling v2 (pooling with dilation support) backward propagation primitiv...
dnnl_status_t DNNL_API dnnl_pooling_v2_forward_desc_init(dnnl_pooling_v2_desc_t *pool_desc, dnnl_prop_kind_t prop_kind, dnnl_alg_kind_t alg_kind, const dnnl_memory_desc_t *src_desc, const dnnl_memory_desc_t *dst_desc, const dnnl_dims_t strides, const dnnl_dims_t kernel, const dnnl_dims_t dilation, const dnnl_dims_t padding_l, const dnnl_dims_t padding_r)
Initializes a descriptor for pooling v2 (pooling with dilation support) forward propagation primitive...
#define DNNL_ARG_DIFF_SRC
A special mnemonic for primitives that have a single diff source argument.
Definition: dnnl_types.h:2374
#define DNNL_ARG_DIFF_BIAS
Gradient (diff) of the bias tensor argument.
Definition: dnnl_types.h:2443
#define DNNL_ARG_DIFF_WEIGHTS
A special mnemonic for primitives that have a single diff weights argument.
Definition: dnnl_types.h:2416
dnnl_status_t DNNL_API dnnl_primitive_desc_create(dnnl_primitive_desc_t *primitive_desc, const_dnnl_op_desc_t op_desc, const_dnnl_primitive_attr_t attr, dnnl_engine_t engine, const_dnnl_primitive_desc_t hint_forward_primitive_desc)
Creates a primitive descriptor.
#define DNNL_ARG_DST
A special mnemonic for destination argument for primitives that have a single destination.
Definition: dnnl_types.h:2307
const dnnl_memory_desc_t DNNL_API * dnnl_primitive_desc_query_md(const_dnnl_primitive_desc_t primitive_desc, dnnl_query_t what, int index)
Queries primitive descriptor for a memory descriptor.
#define DNNL_ARG_WORKSPACE
Workspace tensor argument.
Definition: dnnl_types.h:2366
dnnl_status_t DNNL_API dnnl_primitive_execute(const_dnnl_primitive_t primitive, dnnl_stream_t stream, int nargs, const dnnl_exec_arg_t *args)
Executes a primitive.
dnnl_status_t DNNL_API dnnl_primitive_desc_destroy(dnnl_primitive_desc_t primitive_desc)
Destroys a primitive descriptor.
#define DNNL_ARG_FROM
A special mnemonic for reorder source argument.
Definition: dnnl_types.h:2289
dnnl_status_t DNNL_API dnnl_primitive_destroy(dnnl_primitive_t primitive)
Destroys a primitive.
#define DNNL_ARG_SRC
A special mnemonic for source argument for primitives that have a single source.
Definition: dnnl_types.h:2283
#define DNNL_ARG_DIFF_DST
A special mnemonic for primitives that have a single diff destination argument.
Definition: dnnl_types.h:2395
dnnl_status_t DNNL_API dnnl_primitive_create(dnnl_primitive_t *primitive, const_dnnl_primitive_desc_t primitive_desc)
Creates a primitive.
#define DNNL_ARG_BIAS
Bias tensor argument.
Definition: dnnl_types.h:2357
#define DNNL_ARG_WEIGHTS
A special mnemonic for primitives that have a single weights argument.
Definition: dnnl_types.h:2330
#define DNNL_ARG_TO
A special mnemonic for reorder destination argument.
Definition: dnnl_types.h:2310
@ dnnl_lrn_across_channels
Local response normalization (LRN) across multiple channels.
Definition: dnnl_types.h:1187
@ dnnl_eltwise_relu
Eltwise: ReLU.
Definition: dnnl_types.h:1120
@ dnnl_convolution_direct
Direct convolution.
Definition: dnnl_types.h:1110
@ dnnl_pooling_max
Max pooling.
Definition: dnnl_types.h:1179
@ dnnl_query_weights_md
weights memory descriptor desc
Definition: dnnl_types.h:2566
@ dnnl_query_src_md
source memory desc
Definition: dnnl_types.h:2564
@ dnnl_query_workspace_md
workspace memory desc
Definition: dnnl_types.h:2570
@ dnnl_query_diff_src_md
source gradient memory desc
Definition: dnnl_types.h:2565
@ dnnl_query_diff_weights_md
weights grad. memory desc
Definition: dnnl_types.h:2567
@ dnnl_query_dst_md
destination memory desc
Definition: dnnl_types.h:2568
@ dnnl_query_diff_dst_md
destination grad. memory desc
Definition: dnnl_types.h:2569
@ dnnl_forward
Forward data propagation (alias for dnnl_forward_training).
Definition: dnnl_types.h:1040
dnnl_status_t DNNL_API dnnl_reorder_primitive_desc_create(dnnl_primitive_desc_t *reorder_primitive_desc, const dnnl_memory_desc_t *src_desc, dnnl_engine_t src_engine, const dnnl_memory_desc_t *dst_desc, dnnl_engine_t dst_engine, const_dnnl_primitive_attr_t attr)
Creates a primitive descriptor for a reorder primitive.
dnnl_status_t DNNL_API dnnl_stream_wait(dnnl_stream_t stream)
Waits for all primitives in the execution stream to finish computations.
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
dnnl_status_t
Status values returned by the library functions.
Definition: dnnl_types.h:39
@ dnnl_success
The operation was successful.
Definition: dnnl_types.h:41
A descriptor of a convolution operation.
Definition: dnnl_types.h:1534
A descriptor of a element-wise operation.
Definition: dnnl_types.h:1609
An opaque structure to describe an engine.
A structure that contains an index and a memory object, and is used to pass arguments to dnnl_primiti...
Definition: dnnl_types.h:2475
dnnl_memory_t memory
Input/output memory.
Definition: dnnl_types.h:2477
int arg
An argument index, e.g. DNNL_ARG_SRC.
Definition: dnnl_types.h:2476
A descriptor of a Local Response Normalization (LRN) operation.
Definition: dnnl_types.h:1796
Memory descriptor.
Definition: dnnl_types.h:1445
An opaque structure to describe a memory.
A descriptor of a pooling operation.
Definition: dnnl_types.h:1734
An opaque structure to describe a primitive descriptor.
An opaque structure to describe a primitive.
An opaque structure to describe an execution stream.