clDNN
example_cldnn.cpp
1 #include <api/CPP/memory.hpp>
2 #include <api/CPP/topology.hpp>
3 #include <api/CPP/reorder.hpp>
4 #include <api/CPP/input_layout.hpp>
5 #include <api/CPP/convolution.hpp>
6 #include <api/CPP/data.hpp>
7 #include <api/CPP/pooling.hpp>
8 #include <api/CPP/fully_connected.hpp>
9 #include <api/CPP/softmax.hpp>
10 #include <api/CPP/engine.hpp>
11 #include <api/CPP/network.hpp>
12 
13 #include <iostream>
14 
15 using namespace cldnn;
16 using namespace std;
17 
19  input_channels = 1,
20  input_size = 28,
21  conv1_out_channels = 20,
22  conv2_out_channels = 50,
23  conv_krnl_size = 5,
24  fc1_num_outs = 500,
25  fc2_num_outs = 10;
26 
27 // Create layout with same sizes but new format.
28 layout create_reordering_layout(format new_format, const layout& src_layout)
29 {
30  return { src_layout.data_type, new_format, src_layout.size };
31 }
32 
33 // Create MNIST topology
34 topology create_topology(const layout& in_layout, const memory& conv1_weights_mem, const memory& conv1_bias_mem )
35 {
36  auto data_type = in_layout.data_type;
37 
38  // Create input_layout description
39  // "input" - is the primitive id inside topology
40  input_layout input("input", in_layout);
41 
42  // Create topology object with 2 primitives
44  // 1. input layout primitive.
45  input,
46  // 2. reorder primitive with id "reorder_input"
47  reorder("reorder_input",
48  // input primitive for reorder (implicitly converted to primitive_id)
49  input,
50  // output layout for reorder
51  create_reordering_layout(format::yxfb, in_layout))
52  );
53 
54  // Create data primitive - its content should be set already.
55  cldnn::data conv1_weights( "conv1_weights", conv1_weights_mem );
56 
57  // Add primitive to topology
58  topology.add(conv1_weights);
59 
60  // Emplace new primitive to topology
61  topology.add<cldnn::data>({ "conv1_bias", conv1_bias_mem });
62 
63  // Emplace 2 primitives
64  topology.add(
65  // Convolution primitive with id "conv1"
66  convolution("conv1",
67  "reorder_input", // primitive id of the convolution's input
68  { conv1_weights }, // weights primitive id is taken from the object
69  { "conv1_bias" } // bias primitive id
70  ),
71  // Pooling id: "pool1"
72  pooling("pool1",
73  "conv1", // Input: "conv1"
74  pooling_mode::max, // Pooling mode: MAX
75  spatial(2,2), // stride: 2
76  spatial(2,2) // kernel_size: 2
77  )
78  );
79 
80  // Conv2 weights data is not available now, so just declare its layout
81  layout conv2_weights_layout(data_type, format::bfyx,{ conv2_out_channels, conv1_out_channels, conv_krnl_size, conv_krnl_size });
82 
83  // Define the rest of topology.
84  topology.add(
85  // Input layout for conv2 weights. Data will passed by network::set_input_data()
86  input_layout("conv2_weights", conv2_weights_layout),
87  // Input layout for conv2 bias.
88  input_layout("conv2_bias", { data_type, format::bfyx, spatial(conv2_out_channels) }),
89  // Second convolution id: "conv2"
90  convolution("conv2",
91  "pool1", // Input: "pool1"
92  { "conv2_weights" }, // Weights: input_layout "conv2_weights"
93  { "conv2_bias" } // Bias: input_layout "conv2_bias"
94  ),
95  // Second pooling id: "pool2"
96  pooling("pool2",
97  "conv2", // Input: "conv2"
98  pooling_mode::max, // Pooling mode: MAX
99  spatial(2, 2), // stride: 2
100  spatial(2, 2) // kernel_size: 2
101  ),
102  // Fully connected (inner product) primitive id "fc1"
103  fully_connected("fc1",
104  "pool2", // Input: "pool2"
105  "fc1_weights", // "fc1_weights" will be added to the topology later
106  "fc1_bias", // will be defined later
107  true // Use built-in Relu. Slope is set to 0 by default.
108  ),
109  // Second FC/IP primitive id: "fc2", input: "fc1".
110  // Weights ("fc2_weights") and biases ("fc2_bias") will be defined later.
111  // Built-in Relu is disabled by default.
112  fully_connected("fc2", "fc1", "fc2_weights", "fc2_bias"),
113  // The "softmax" primitive is not an input for any other,
114  // so it will be automatically added to network outputs.
115  softmax("softmax", "fc2")
116  );
117  return topology;
118 }
119 
120 // Copy from a vector to cldnn::memory
121 void copy_to_memory(memory& mem, const vector<float>& src)
122 {
123  cldnn::pointer<float> dst(mem);
124  std::copy(src.begin(), src.end(), dst.begin());
125 }
126 
127 // Execute network
128 int recognize_image(network& network, const memory& input_memory)
129 {
130  // Set/update network input
131  network.set_input_data("input", input_memory);
132 
133  // Start network execution
134  auto outputs = network.execute();
135 
136  // get_memory() blocks output generation completed
137  auto output = outputs.at("softmax").get_memory();
138 
139  // Get direct access to output memory
140  cldnn::pointer<float> out_ptr(output);
141 
142  // Analyze result
143  auto max_element_pos = max_element(out_ptr.begin(), out_ptr.end());
144  return static_cast<int>(distance(out_ptr.begin(), max_element_pos));
145 }
146 
147 // User-defined helpers which are out of this example scope
148 // //////////////////////////////////////////////////////////////
149 // Loads file to a vector of floats.
150 vector<float> load_data(const string&) { return{ 0 }; }
151 
152 // Allocates memory and loads data from file.
153 // Memory layout is taken from file.
154 memory load_mem(const engine& eng, const string&) {
155  //return a dummy value
156  return memory::allocate(eng, layout{ data_types::f32, format::bfyx, { 1, 1, 1, 1 } });
157 }
158 
159 // Load image, resize to [x,y] and store in a vector of floats
160 // in the order "bfyx".
161 vector<float> load_image_bfyx(const string&, int, int) { return{ 0 }; }
162 // //////////////////////////////////////////////////////////////
163 
164 int main_func()
165 {
166  // Use data type: float
167  auto data_type = type_to_data_type<float>::value;
168 
169  // Network input layout
170  layout in_layout(
171  data_type, // stored data type
172  format::bfyx, // data stored in order batch-channel-Y-X, where X coordinate changes first.
173  {1, input_channels, input_size, input_size} // batch: 1, channels: 1, Y: 28, X: 28
174  );
175 
176  // Create memory for conv1 weights
177  layout conv1_weights_layout(data_type, format::bfyx,{ conv1_out_channels, input_channels, conv_krnl_size, conv_krnl_size });
178  vector<float> my_own_buffer = load_data("conv1_weights.bin");
179  // The conv1_weights_mem is attached to my_own_buffer, so my_own_buffer should not be changed or descroyed until network execution completion.
180  auto conv1_weights_mem = memory::attach(conv1_weights_layout, my_own_buffer.data(), my_own_buffer.size());
181 
182  // Create default engine
184 
185  // Create memory for conv1 bias
186  layout conv1_bias_layout(data_type, format::bfyx, spatial(20));
187  // Memory allocation requires engine
188  auto conv1_bias_mem = memory::allocate(engine, conv1_bias_layout);
189  // The memory is allocated by library, so we do not need to care about buffer lifetime.
190  copy_to_memory(conv1_bias_mem, load_data("conv1_bias.bin"));
191 
192  // Get new topology
193  cldnn::topology topology = create_topology(in_layout, conv1_weights_mem, conv1_bias_mem);
194 
195  // Define network data not defined in create_topology()
196  topology.add(
197  cldnn::data("fc1_weights", load_mem(engine, "fc1_weights.data")),
198  cldnn::data("fc1_bias", load_mem(engine, "fc1_bias.data")),
199  cldnn::data("fc2_weights", load_mem(engine, "fc2_weights.data")),
200  cldnn::data("fc2_bias", load_mem(engine, "fc2_bias.data"))
201  );
202 
203  // Build the network. Allow implicit data optimizations.
204  // The "softmax" primitive is not used as an input for other primitives,
205  // so we do not need to explicitly select it in build_options::outputs()
207 
208  // Set network data which was not known at topology creation.
209  network.set_input_data("conv2_weights", load_mem(engine, "conv2_weights.data"));
210  network.set_input_data("conv2_bias", load_mem(engine, "conv2_bias.data"));
211 
212  // Allocate memory for input image.
213  auto input_memory = memory::allocate(engine, in_layout);
214 
215  // Run network 2 times with different images.
216  for (auto img_name : { "one.jpg", "two.jpg" })
217  {
218  // Reuse image memory.
219  copy_to_memory(input_memory, load_image_bfyx("one.jpg", in_layout.size.spatial[0], in_layout.size.spatial[1]));
220  auto result = recognize_image(network, input_memory);
221  cout << img_name << " recognized as" << result << endl;
222  }
223 
224  return 0;
225 }
std::map< primitive_id, network_output > execute(const std::vector< event > &dependencies={}) const
Executes network and returns the list of network_output.
Definition: network.hpp:246
void set_input_data(const primitive_id &id, const memory &mem) const
Provides memory for input_layout primitives defined by user in source topology.
Definition: network.hpp:122
Maximum-pooling method.
Performs forward fully connected layer (inner product). Also supports built-in Relu cldnn_activation_...
data_types data_type
Data type stored in memory (see. data_types)
Definition: layout.hpp:373
Changes how data is ordered in memory. Value type is not changed & all information is preserved...
Definition: reorder.hpp:36
Provides input data to topology.
Definition: data.hpp:36
mutable_array_ref< value_type > spatial
Spatial dimensions.
Definition: tensor.hpp:267
tensor size
The size of the memory (excluding padding)
Definition: layout.hpp:379
static memory attach(const cldnn::layout &layout, T *ptr, size_t size)
Definition: memory.hpp:65
User selected list of program outputs.
Performs "pooling" operation which is a form of non-linear down-sampling.
Definition: pooling.hpp:44
batch first, feature and than spatials
Definition: tensor.hpp:79
Provides input layout for a data to be passed later to network.
Network topology to be defined by user.
Definition: topology.hpp:33
void add(PType const &desc)
Adds a primitive to topology.
Definition: topology.hpp:75
static memory allocate(const engine &engine, const layout &layout)
Allocate memory on engine using specified layout.
Definition: memory.hpp:50
int32_t value_type
Values type stored in tensor.
Definition: tensor.hpp:262
Represents memory formats (orders). In CNN most of data is described as 4 dimensional blocks...
Definition: tensor.hpp:75
Converts C++ type to data_types .
Definition: layout.hpp:41
the most common format for activations in clDNN.
Definition: tensor.hpp:81
Executable network allocated from program.
Definition: network.hpp:59
Normalizes results so they sum to 1.
Definition: softmax.hpp:39
Represents clDNN engine object.
Definition: engine.hpp:110
Helper class to get an access memory data.
Definition: memory.hpp:36
Represents buffer with particular layout.
Definition: memory.hpp:42
Describes memory layout.
Definition: layout.hpp:223
static std::shared_ptr< const build_option > optimize_data(bool enable=false)
Enable implicit reordering for user inputs (default: false).
Performs forward spatial convolution with weight sharing. Also supports built-in Relu cldnn_activatio...
Definition: convolution.hpp:34