This C++ API example demonstrates how to run AlexNet's conv3 and relu3 with int8 data type.
#include <iostream>
#include <numeric>
#include <string>
memory::dim product(const memory::dims &dims) {
return std::accumulate(dims.begin(), dims.end(), (memory::dim)1,
std::multiplies<memory::dim>());
}
void simple_net_int8() {
const int batch = 8;
memory::dims conv_src_tz = { batch, 256, 13, 13 };
memory::dims conv_weights_tz = { 384, 256, 3, 3 };
memory::dims conv_bias_tz = { 384 };
memory::dims conv_dst_tz = { batch, 384, 13, 13 };
memory::dims conv_strides = { 1, 1 };
memory::dims conv_padding = { 1, 1 };
const std::vector<float> src_scales = { 1.8f };
const std::vector<float> weight_scales = { 2.0f };
const std::vector<float> bias_scales = { 1.0f };
const std::vector<float> dst_scales = { 0.55f };
std::vector<float> conv_scales(384);
const int scales_half = 384 / 2;
std::fill(conv_scales.begin(), conv_scales.begin() + scales_half, 0.3f);
std::fill(conv_scales.begin() + scales_half + 1, conv_scales.end(), 0.8f);
const int src_mask = 0;
const int weight_mask = 0;
const int bias_mask = 0;
const int dst_mask = 0;
const int conv_mask = 2;
std::vector<float> user_src(batch * 256 * 13 * 13);
std::vector<float> user_dst(batch * 384 * 13 * 13);
std::vector<float> conv_weights(product(conv_weights_tz));
std::vector<float> conv_bias(product(conv_bias_tz));
auto user_src_memory =
memory({ { conv_src_tz }, dt::f32, tag::nchw },
cpu_engine, user_src.data());
auto user_weights_memory
=
memory({ { conv_weights_tz }, dt::f32, tag::oihw }, cpu_engine,
conv_weights.data());
auto user_bias_memory =
memory({ { conv_bias_tz }, dt::f32, tag::x },
cpu_engine, conv_bias.data());
auto conv_src_md =
memory::desc({ conv_src_tz }, dt::u8, tag::any);
auto conv_bias_md =
memory::desc({ conv_bias_tz }, dt::s8, tag::any);
auto conv_weights_md =
memory::desc({ conv_weights_tz }, dt::s8, tag::any);
auto conv_dst_md =
memory::desc({ conv_dst_tz }, dt::u8, tag::any);
conv_dst_md, conv_strides, conv_padding, conv_padding);
const float ops_scale = 1.f;
const float ops_alpha = 0.f;
const float ops_beta = 0.f;
try {
conv_desc, conv_attr, cpu_engine);
std::cerr << "Intel MKL-DNN does not have int8 convolution "
"implementation that supports this system. Please refer to "
"the developer guide for details." << std::endl;
}
throw;
}
conv_desc, conv_attr, cpu_engine);
auto conv_src_memory =
memory(conv_prim_desc.src_desc(), cpu_engine);
auto src_reorder_pd = reorder::primitive_desc(cpu_engine,
user_src_memory.get_desc(), cpu_engine,
conv_src_memory.get_desc(), src_attr);
auto src_reorder =
reorder(src_reorder_pd);
src_reorder.execute(s, user_src_memory, conv_src_memory);
auto conv_weights_memory
=
memory(conv_prim_desc.weights_desc(), cpu_engine);
auto weight_reorder_pd = reorder::primitive_desc(cpu_engine,
user_weights_memory.
get_desc(), cpu_engine,
conv_weights_memory.get_desc(), weight_attr);
auto weight_reorder =
reorder(weight_reorder_pd);
weight_reorder.execute(s, user_weights_memory, conv_weights_memory);
auto conv_bias_memory =
memory(conv_prim_desc.bias_desc(), cpu_engine);
auto bias_reorder_pd = reorder::primitive_desc(cpu_engine,
user_bias_memory.
get_desc(), cpu_engine,
conv_bias_memory.get_desc(), bias_attr);
auto bias_reorder =
reorder(bias_reorder_pd);
bias_reorder.execute(s, user_bias_memory, conv_bias_memory);
auto conv_dst_memory =
memory(conv_prim_desc.dst_desc(), cpu_engine);
conv.execute(s,
{ { MKLDNN_ARG_SRC, conv_src_memory },
{ MKLDNN_ARG_WEIGHTS, conv_weights_memory },
{ MKLDNN_ARG_BIAS, conv_bias_memory },
{ MKLDNN_ARG_DST, conv_dst_memory } });
auto user_dst_memory =
memory({ { conv_dst_tz }, dt::f32, tag::nchw },
cpu_engine, user_dst.data());
auto dst_reorder_pd = reorder::primitive_desc(cpu_engine,
conv_dst_memory.get_desc(), cpu_engine,
user_dst_memory.get_desc(), dst_attr);
auto dst_reorder =
reorder(dst_reorder_pd);
dst_reorder.execute(s, conv_dst_memory, user_dst_memory);
}
int main(int argc, char **argv) {
try {
simple_net_int8();
std::cout << "Simple-net-int8 example passed!" << std::endl;
std::cerr << "status: " << e.status << std::endl;
std::cerr <<
"message: " << e.
message << std::endl;
}
return 0;
}