Caffe2 - C++ API
A deep learning, cross platform ML framework
convert_and_benchmark.cc
1 
17 #include <opencv2/opencv.hpp>
18 #include <cmath>
19 #include <fstream>
20 
21 #include "caffe2/core/common.h"
22 #include "caffe2/core/db.h"
23 #include "caffe2/core/init.h"
24 #include "caffe2/core/logging.h"
25 #include "caffe2/core/timer.h"
26 #include "caffe2/proto/caffe2_pb.h"
27 #include "caffe2/utils/proto_utils.h"
28 #include "caffe2/utils/string_utils.h"
29 #include "caffe2/utils/bench_utils.h"
30 
31 #include "binaries/benchmark_args.h"
32 #include "binaries/benchmark_helper.h"
33 
34 #include <observers/net_observer_reporter_print.h>
35 #include <observers/observer_config.h>
36 #include <observers/perf_observer.h>
37 
38 
39 C10_DEFINE_int(
40  batch_size,
41  -1,
42  "Specify the batch size of the input. The number of items in the "
43  "input needs to be multiples of the batch size. If the batch size "
44  "is less than 0, all inputs are in one batch.")
45 C10_DEFINE_bool(color, true, "If set, load images in color.");
46 C10_DEFINE_string(
47  crop,
48  "-1,-1",
49  "The center cropped hight and width. If the value is less than zero, "
50  "it is not cropped.");
51 C10_DEFINE_string(input_image_files, "", "Files containing imput images");
52 C10_DEFINE_string(input_text_files, "", "Text files to be written to blobs");
53 C10_DEFINE_string(
54  preprocess,
55  "",
56  "Options to specify the preprocess routines. The available options are "
57  "subtract128, normalize, mean, std, bgrtorgb. If multiple steps are provided, they "
58  "are separated by comma (,) in sequence.");
59 C10_DEFINE_string(
60  report_time,
61  "",
62  "Report the conversion stage time to screen. "
63  "The format of the string is <type>|<identifier>. "
64  "The valid type is 'json'. "
65  "The valid identifier is nothing or an identifer that prefix every line");
66 C10_DEFINE_string(
67  scale,
68  "-1,-1",
69  "Scale the images to be within the min,max box. The shorter edge is "
70  "min pixels. But if the other edge is more than the max pixels, the "
71  "other edge and scaled to max pixels (and the shorter edge can be less "
72  "than the min pixels");
73 C10_DEFINE_bool(warp, false, "If warp is set, warp the images to square.");
74 
75 namespace caffe2 {
76 
77 void reportTime(
78  std::string type,
79  double ts,
80  std::string metric,
81  std::string unit) {
82  if (FLAGS_report_time == "") {
83  return;
84  }
85  vector<string> s = caffe2::split('|', FLAGS_report_time);
86  assert(s[0] == "json");
87  std::string identifier = "";
88  if (s.size() > 1) {
89  identifier = s[1];
90  }
91  std::cout << identifier << "{\"type\": \"" << type << "\", \"value\": " << ts
92  << ", \"metric\": \"" << metric << "\", \"unit\": \"" << unit
93  << "\"}" << std::endl;
94 }
95 
96 void splitSizes(const std::string& arg, int* ptr0, int* ptr1) {
97  vector<string> sizes = caffe2::split(',', arg);
98  if (sizes.size() == 2) {
99  *ptr0 = std::stoi(sizes[0]);
100  *ptr1 = std::stoi(sizes[1]);
101  } else if (sizes.size() == 1) {
102  *ptr0 = std::stoi(sizes[0]);
103  *ptr1 = std::stoi(sizes[0]);
104  } else {
105  assert(false);
106  }
107 }
108 
109 
110 cv::Mat resizeImage(cv::Mat& img) {
111  int min_size, max_size;
112  splitSizes(FLAGS_scale, &min_size, &max_size);
113  if ((min_size <= 0) && (max_size <= 0)) {
114  return img;
115  }
116  if (max_size < 0) {
117  max_size = INT_MAX;
118  }
119  assert(min_size <= max_size);
120 
121  int im_min_size = img.rows > img.cols ? img.cols : img.rows;
122  int im_max_size = img.rows > img.cols ? img.rows : img.cols;
123 
124  double im_scale = 1.0 * min_size / im_min_size;
125  if (im_scale * im_max_size > max_size) {
126  im_scale = 1.0 * max_size / im_max_size;
127  }
128  int scaled_width = int(round(img.cols * im_scale));
129  int scaled_height = int(round(img.rows * im_scale));
130  assert((scaled_width <= max_size) && (scaled_height <= max_size));
131  if ((scaled_width < min_size) || (scaled_height < min_size)) {
132  assert((scaled_width == max_size) || (scaled_height == max_size));
133  } else {
134  assert((scaled_width == min_size) || (scaled_height == min_size));
135  }
136  cv::Mat resized_img;
137  cv::resize(
138  img,
139  resized_img,
140  cv::Size(),
141  im_scale,
142  im_scale,
143  cv::INTER_LINEAR);
144  return resized_img;
145 }
146 
147 cv::Mat cropToRec(cv::Mat& img, int* height_ptr, int* width_ptr) {
148  int height = *height_ptr;
149  int width = *width_ptr;
150  if ((height > 0) && (width > 0) &&
151  ((img.rows != height) || (img.cols != width))) {
152  cv::Mat cropped_img, cimg;
153  cv::Rect roi;
154  roi.x = int((img.cols - width) / 2);
155  roi.y = int((img.rows - height) / 2);
156  roi.x = roi.x < 0 ? 0 : roi.x;
157  roi.y = roi.y < 0 ? 0 : roi.y;
158  width = width > img.cols ? img.cols : width;
159  height = height > img.rows ? img.rows : height;
160  roi.width = width;
161  roi.height = height;
162  assert(
163  0 <= roi.x && 0 <= roi.width && roi.x + roi.width <= img.cols &&
164  0 <= roi.y && 0 <= roi.height && roi.y + roi.height <= img.rows);
165  cropped_img = img(roi);
166  // Make the image in continuous space in memory
167  cimg = cropped_img.clone();
168  *height_ptr = height;
169  *width_ptr = width;
170  return cimg;
171  } else {
172  return img;
173  }
174 }
175 
176 std::vector<float> convertToVector(cv::Mat& img) {
177  std::vector<float> normalize(3, 1);
178  std::vector<float> mean(3, 0);
179  std::vector<float> std(3, 1);
180  bool bgrtorgb = false;
181  int size = img.cols * img.rows;
182  vector<string> steps = caffe2::split(',', FLAGS_preprocess);
183  for (int i = 0; i < steps.size(); i++) {
184  auto step = steps[i];
185  if (step == "subtract128") {
186  mean = {128, 128, 128};
187  std = {1, 1, 1};
188  normalize = {1, 1, 1};
189  } else if (step == "normalize") {
190  normalize = {255, 255, 255};
191  } else if (step == "mean") {
192  mean = {0.406f, 0.456f, 0.485f};
193  } else if (step == "std") {
194  std = {0.225f, 0.224f, 0.229f};
195  } else if (step == "bgrtorgb") {
196  bgrtorgb = true;
197  } else {
198  CAFFE_ENFORCE(
199  false,
200  "Unsupported preprocess step. The supported steps are: subtract128, "
201  "normalize,mean, std, swaprb.");
202  }
203  }
204 
205  int C = FLAGS_color ? 3 : 1;
206  int total_size = C * size;
207  std::vector<float> values(total_size);
208  if (C == 1) {
209  cv::MatIterator_<float> it, end;
210  int idx = 0;
211  for (it = img.begin<float>(), end = img.end<float>(); it != end; ++it) {
212  values[idx++] = (*it / normalize[0] - mean[0]) / std[0];
213  }
214  } else {
215  int i = 0;
216  cv::MatIterator_<cv::Vec3f> it, end;
217  int b = bgrtorgb ? 2 : 0;
218  int g = 1;
219  int r = bgrtorgb ? 0 : 2;
220  for (it = img.begin<cv::Vec3f>(), end = img.end<cv::Vec3f>(); it != end;
221  ++it, i++) {
222  values[i] = (((*it)[b] / normalize[0] - mean[0]) / std[0]);
223  int offset = size + i;
224  values[offset] = (((*it)[g] / normalize[1] - mean[1]) / std[1]);
225  offset = size + offset;
226  values[offset] = (((*it)[r] / normalize[2] - mean[2]) / std[2]);
227  }
228  }
229  return values;
230 }
231 
232 std::vector<float> convertOneImage(
233  std::string& filename,
234  int* height_ptr,
235  int* width_ptr) {
236  assert(filename[0] != '~');
237 
238  std::cout << "Converting " << filename << std::endl;
239 
240  // Load image
241  cv::Mat img_uint8 = cv::imread(
242 #if CV_MAJOR_VERSION <= 3
243  filename, FLAGS_color ? CV_LOAD_IMAGE_COLOR : CV_LOAD_IMAGE_GRAYSCALE);
244 #else
245  filename, FLAGS_color ? cv::IMREAD_COLOR : cv::IMREAD_GRAYSCALE);
246 #endif
247  caffe2::Timer timer;
248  timer.Start();
249  cv::Mat img;
250  // Convert image to floating point values
251  img_uint8.convertTo(img, CV_32F);
252  // Resize image
253  cv::Mat resized_img = resizeImage(img);
254 
255  int height, width;
256  splitSizes(FLAGS_crop, &height, &width);
257  if ((height <= 0) || (width <= 0)) {
258  height = resized_img.rows;
259  width = resized_img.cols;
260  }
261  cv::Mat crop = cropToRec(resized_img, &height, &width);
262 
263  // Assert we don't have to deal with alignment
264  DCHECK(crop.isContinuous());
265  assert(crop.rows == height);
266  assert(crop.cols == width);
267  std::vector<float> one_image_values = convertToVector(crop);
268  *height_ptr = height;
269  *width_ptr = width;
270  double ts = timer.MicroSeconds();
271  reportTime("image_preprocess", ts, "convert", "us");
272  return one_image_values;
273 }
274 
275 int getBatchSize(int num_items) {
276  int batch_size = FLAGS_batch_size;
277  if (batch_size < 0) {
278  batch_size = num_items;
279  } else {
280  assert(num_items % batch_size == 0);
281  }
282  return batch_size;
283 }
284 
285 TensorProtos writeValues(
286  std::vector<std::vector<std::vector<float>>>& values,
287  std::vector<std::vector<int>>& dims) {
288 
289  caffe2::Timer timer;
290  timer.Start();
291 
292  assert(dims.size() == values.size());
293  int num_batches = dims.size();
294 
295  TensorProtos protos;
296  for (int k = 0; k < num_batches; k++) {
297  TensorProto* data;
298  data = protos.add_protos();
299  data->set_data_type(TensorProto::FLOAT);
300  auto one_dim = dims[k];
301  for (int dim : one_dim) {
302  data->add_dims(dim);
303  }
304  int batch_size = one_dim[0];
305  long long int entry_size = 1;
306  for (int i = 1; i < one_dim.size(); i++) {
307  entry_size *= one_dim[i];
308  }
309 
310  // Not optimized
311  for (int i = 0; i < batch_size; i++) {
312  assert(values[k][i].size() == entry_size);
313  for (int j = 0; j < values[k][i].size(); j++) {
314  data->add_float_data(values[k][i][j]);
315  }
316  }
317  }
318  double ts = timer.MicroSeconds();
319  reportTime("preprocess", ts, "data_pack", "us");
320 
321  return protos;
322 }
323 
324 TensorProtos convertImages(std::string& image_file) {
325  vector<string> file_names;
326  if (image_file != "") {
327  std::ifstream infile(image_file);
328  std::string line;
329  while (std::getline(infile, line)) {
330  vector<string> file_name = caffe2::split(',', line);
331  string name;
332  if (file_name.size() == 3) {
333  name = file_name[2];
334  } else {
335  name = line;
336  }
337  file_names.push_back(name);
338  }
339  } else {
340  TensorProtos proto;
341  return proto;
342  }
343  int batch_size = getBatchSize(file_names.size());
344  int num_batches = file_names.size() / batch_size;
345  assert(file_names.size() == batch_size * num_batches);
346  std::vector<std::vector<std::vector<float>>> values;
347  std::vector<std::vector<int>> dims;
348  int C = FLAGS_color ? 3 : 1;
349  for (int k = 0; k < num_batches; k++) {
350  std::vector<std::vector<float>> one_value;
351  int height = -1;
352  int width = -1;
353  for (int i = 0; i < batch_size; i++) {
354  int idx = k * batch_size + i;
355  int one_height, one_width;
356  std::vector<float> one_image_values =
357  convertOneImage(file_names[idx], &one_height, &one_width);
358  if (height < 0 && width < 0) {
359  height = one_height;
360  width = one_width;
361  } else {
362  assert(height == one_height);
363  assert(width == one_width);
364  }
365  one_value.push_back(one_image_values);
366  }
367  vector<int> one_dim = {batch_size, C, height, width};
368  dims.push_back(one_dim);
369  values.push_back(one_value);
370  }
371  return writeValues(values, dims);
372 }
373 
374 template <class TYPE>
375 vector<TYPE> splitString(std::string& line) {
376  vector<string> vector_str = caffe2::split(',', line);
377  vector<TYPE> vector_int;
378  for (string str : vector_str) {
379  vector_int.push_back((TYPE)std::stod(str));
380  }
381  return vector_int;
382 }
383 
384 /* Convert the values in a json file to blobs
385  The format of the json file should be:
386  <number of items>, <dim2>.... (dimensions of items)
387  <entry>, <entry>, <entry>... (all entries in one item)
388  <entry>, <entry>, <entry>...
389  ....
390 */
391 TensorProtos convertValues(std::string& file_name) {
392  if (file_name == "") {
393  TensorProtos proto;
394  return proto;
395  }
396  std::ifstream infile(file_name);
397  std::string line;
398  std::getline(infile, line);
399  vector<int> file_dims = splitString <int>(line);
400  assert(file_dims.size() >= 2);
401 
402  int num_items = file_dims[0];
403  int batch_size = getBatchSize(num_items);
404  int num_batches = num_items / batch_size;
405  assert(num_items == batch_size * num_batches);
406  vector<string> lines;
407  while (std::getline(infile, line)) {
408  lines.push_back(line);
409  }
410  assert(lines.size() == num_items);
411  std::vector<std::vector<std::vector<float>>> values;
412  std::vector<std::vector<int>> dims;
413  for (int i = 0; i < num_batches; i++) {
414  std::vector<std::vector<float>> one_value;
415  int num = -1;
416  for (int j = 0; j < batch_size; j++) {
417  int idx = i * batch_size + j;
418  std::string line = lines[idx];
419  vector<float> item = splitString<float>(line);
420  if (num < 0) {
421  num = item.size();
422  } else {
423  assert(num == item.size());
424  }
425  one_value.push_back(item);
426  }
427  vector<int> batch_dims = file_dims;
428  batch_dims[0] = batch_size;
429  dims.push_back(batch_dims);
430  values.push_back(one_value);
431  }
432 
433  return writeValues(values, dims);
434 }
435 
436 } // namespace caffe2
437 
438 void observerConfig() {
439  caffe2::ClearGlobalNetObservers();
440  caffe2::AddGlobalNetObserverCreator([](caffe2::NetBase* subject) {
441  return caffe2::make_unique<caffe2::PerfNetObserver>(subject);
442  });
443  caffe2::ObserverConfig::setReporter(
444  caffe2::make_unique<caffe2::NetObserverReporterPrint>());
445 }
446 
447 bool backendCudaSet(const string& backend) {
448  bool run_on_gpu = false;
449  if (backend == "cuda") {
450 #ifdef __CUDA_ARCH__
451  if (caffe2::HasCudaGPU()) {
452  run_on_gpu = true;
453  } else {
454  CAFFE_THROW("NO GPU support on this host machine");
455  }
456 #else
457  CAFFE_THROW("NO GPU support");
458 #endif
459  }
460  return run_on_gpu;
461 }
462 
463 void setOperatorEngine(caffe2::NetDef* net_def, const string& backend) {
464  if (backend != "builtin") {
465  string engine;
466  if( backend == "nnpack" ) {
467  engine = "NNPACK";
468  } else if ( backend == "eigen" ) {
469  engine = "EIGEN";
470  } else if ( backend == "mkl" ) {
471  engine = "MKLDNN";
472  } else if ( backend == "cuda" ) {
473  engine = "CUDA";
474  } else if ( backend == "dnnlowp" ) {
475  engine = "DNNLOWP";
476  } else if ( backend == "dnnlowp_acc16" ) {
477  engine = "DNNLOWP_ACC16";
478  } else if ( backend == "default" ) {
479  engine = "";
480  } else {
481  engine = "NONE";
482  }
483  CAFFE_ENFORCE(engine != "NONE", "Backend is not supported");
484  for (int i = 0; i < net_def->op_size(); i++) {
485  caffe2::OperatorDef* op_def = net_def->mutable_op(i);
486  op_def->set_engine(engine);
487  }
488  }
489 }
490 
491 void fillInputBlob(
492  shared_ptr<caffe2::Workspace> workspace,
493  map<string, caffe2::TensorProtos>& tensor_protos_map,
494  int iteration) {
495  if (tensor_protos_map.empty()) {
496  return;
497  }
498  static caffe2::TensorDeserializer deserializer;
499  for (auto& tensor_kv : tensor_protos_map) {
500  caffe2::Blob* blob = workspace->GetBlob(tensor_kv.first);
501  if (blob == nullptr) {
502  blob = workspace->CreateBlob(tensor_kv.first);
503  }
504  // todo: support gpu and make this function a tempalte
505  int protos_size = tensor_kv.second.protos_size();
506  if (protos_size == 1 && iteration > 0) {
507  // Do not override the input data if there is only one input data,
508  // since it will clear all caches. Rely on wipe_cache to
509  // clear caches
510  continue;
511  }
512  caffe2::TensorProto* tensor_proto =
513  tensor_kv.second.mutable_protos(iteration % protos_size);
514  BlobSetTensor(blob, deserializer.Deserialize(*tensor_proto));
515  // todo: for other types
516  }
517 }
518 
519 void writeOutput(
520  shared_ptr<caffe2::Workspace> workspace,
521  const bool run_on_gpu,
522  const string& output,
523  const string& output_folder,
524  const bool text_output,
525  const int index,
526  const int num_blobs) {
527  if (output.size() == 0) {
528  return;
529  }
530  string output_prefix = output_folder.size() ? output_folder + "/" : "";
531  vector<string> output_names = caffe2::split(',', output);
532  if (output == "*") {
533  output_names = workspace->Blobs();
534  }
535  for (const string& name : output_names) {
536  CAFFE_ENFORCE(
537  workspace->HasBlob(name),
538  "You requested a non-existing blob: ",
539  name);
540  if (text_output) {
541  if (run_on_gpu) {
542 #ifdef __CUDA_ARCH__
543  writeTextOutput<caffe2::CUDAContext, caffe2::TensorCUDA>(
544  workspace->GetBlob(name)->GetMutable<caffe2::TensorCUDA>(),
545  output_prefix,
546  name,
547  index,
548  num_blobs);
549 #else
550  CAFFE_THROW("Not support GPU.");
551 #endif
552  } else {
553  writeTextOutput<caffe2::CPUContext, caffe2::TensorCPU>(
554  BlobGetMutableTensor(workspace->GetBlob(name), caffe2::CPU),
555  output_prefix,
556  name,
557  index,
558  num_blobs);
559  }
560  } else {
561  // Do not support multiple entries per blob.
562  CAFFE_ENFORCE(
563  index == 0,
564  "Binary file only support one output.");
565  string serialized = SerializeBlob(*workspace->GetBlob(name), name);
566  string output_filename = output_prefix + name;
567  caffe2::WriteStringToFile(serialized, output_filename.c_str());
568  }
569  }
570 }
571 
572 void runNetwork(
573  shared_ptr<caffe2::Workspace> workspace,
574  caffe2::NetDef& net_def,
575  map<string, caffe2::TensorProtos>& tensor_protos_map,
576  const bool wipe_cache,
577  const bool run_individual,
578  const bool run_on_gpu,
579  const bool text_output,
580  const int warmup,
581  const int iter,
582  const int num_blobs,
583  const int sleep_before_run,
584  const int sleep_between_iteration,
585  const int sleep_between_net_and_operator,
586  const std::string& output,
587  const std::string& output_folder) {
588 
589  if (!net_def.has_name()) {
590  net_def.set_name("benchmark");
591  }
592 
593  caffe2::NetBase* net = workspace->CreateNet(net_def);
594  CHECK_NOTNULL(net);
595 
596  LOG(INFO) << "Starting benchmark.";
597  caffe2::ObserverConfig::initSampleRate(1, 1, 1, run_individual, warmup);
598  LOG(INFO) << "Running warmup runs.";
599  for (int i = 0; i < warmup; ++i) {
600  fillInputBlob(workspace, tensor_protos_map, i);
601  CAFFE_ENFORCE(net->Run(), "Warmup run ", i, " has failed.");
602  }
603 
604  if (wipe_cache) {
605  caffe2::wipe_cache();
606  }
607  if (sleep_before_run > 0) {
608  std::this_thread::sleep_for(std::chrono::seconds(sleep_before_run));
609  }
610  LOG(INFO) << "Main runs.";
611  CAFFE_ENFORCE(
612  iter >= 0,
613  "Number of main runs should be non negative, provided ",
614  iter,
615  ".");
616  LOG(INFO) << "net runs.";
617  for (int i = 0; i < iter; ++i) {
618  caffe2::ObserverConfig::initSampleRate(1, 1, 1, 0, warmup);
619  fillInputBlob(workspace, tensor_protos_map, i);
620  if (wipe_cache) {
621  caffe2::wipe_cache();
622  }
623  CAFFE_ENFORCE(net->Run(), "Main run ", i, " has failed.");
624  // Write the output for the first num_blobs times
625  writeOutput(
626  workspace,
627  run_on_gpu,
628  output,
629  output_folder,
630  text_output,
631  i,
632  num_blobs);
633  if (wipe_cache) {
634  caffe2::wipe_cache();
635  }
636  if (sleep_between_iteration > 0) {
637  std::this_thread::sleep_for(
638  std::chrono::seconds(sleep_between_iteration));
639  }
640  }
641  if (run_individual) {
642  LOG(INFO) << "operator runs.";
643  if (sleep_between_net_and_operator > 0) {
644  std::this_thread::sleep_for(
645  std::chrono::seconds(sleep_between_net_and_operator));
646  }
647  for (int i = 0; i < iter; ++i) {
648  caffe2::ObserverConfig::initSampleRate(1, 1, 1, 1, warmup);
649  fillInputBlob(workspace, tensor_protos_map, i);
650  CAFFE_ENFORCE(net->Run(), "Main run ", i, " with operator has failed.");
651  if (wipe_cache) {
652  caffe2::wipe_cache();
653  }
654  if (sleep_between_iteration > 0) {
655  std::this_thread::sleep_for(
656  std::chrono::seconds(sleep_between_iteration));
657  }
658  }
659  }
660 }
661 
662 int benchmark(
663  int argc,
664  char* argv[],
665  const string& FLAGS_backend,
666  const string& FLAGS_init_net,
667  const string& FLAGS_input_dims,
668  int FLAGS_iter,
669  const string& FLAGS_net,
670  const string& FLAGS_output,
671  const string& FLAGS_output_folder,
672  bool FLAGS_run_individual,
673  int FLAGS_sleep_before_run,
674  int FLAGS_sleep_between_iteration,
675  int FLAGS_sleep_between_net_and_operator,
676  bool FLAGS_text_output,
677  int FLAGS_warmup,
678  bool FLAGS_wipe_cache) {
679  // Check arguments to be correct
680  {
681  // Need to check whether file exists, as the file reader does not assert if
682  // file does not exist
683  std::ifstream net_file(FLAGS_net);
684  CAFFE_ENFORCE(net_file.good());
685  net_file.close();
686 
687  std::ifstream init_net_file(FLAGS_init_net);
688  CAFFE_ENFORCE(init_net_file.good());
689  init_net_file.close();
690  }
691 
692  observerConfig();
693  caffe2::ShowLogInfoToStderr();
694 
695  auto workspace = std::make_shared<caffe2::Workspace>(new caffe2::Workspace());
696  bool run_on_gpu = backendCudaSet(FLAGS_backend);
697  // Run initialization network.
698  caffe2::NetDef init_net_def;
699  CAFFE_ENFORCE(ReadProtoFromFile(FLAGS_init_net, &init_net_def));
700  setOperatorEngine(&init_net_def, FLAGS_backend);
701  CAFFE_ENFORCE(workspace->RunNetOnce(init_net_def));
702 
703  // Run main network.
704  caffe2::NetDef net_def;
705  CAFFE_ENFORCE(ReadProtoFromFile(FLAGS_net, &net_def));
706  setOperatorEngine(&net_def, FLAGS_backend);
707 
708  map<string, caffe2::TensorProtos> tensor_protos_map;
709 
710  int num_blobs;
711  vector<string> images = caffe2::split(';', FLAGS_input_image_files);
712  for (int i = 0; i < images.size(); ++i) {
713  vector<string> mapping = caffe2::split(',', images[i]);
714  caffe2::TensorProtos proto_images = caffe2::convertImages(mapping[1]);
715  workspace->CreateBlob(mapping[0]);
716  tensor_protos_map.insert(std::make_pair(mapping[0], proto_images));
717  num_blobs = proto_images.protos_size();
718  }
719 
720  vector<string> values = caffe2::split(';', FLAGS_input_text_files);
721  for (int i = 0; i < values.size(); ++i) {
722  vector<string> mapping = caffe2::split(',', values[i]);
723  caffe2::TensorProtos proto_values = caffe2::convertValues(mapping[1]);
724  workspace->CreateBlob(mapping[0]);
725  tensor_protos_map.insert(std::make_pair(mapping[0], proto_values));
726  num_blobs = proto_values.protos_size();
727  }
728 
729  runNetwork(
730  workspace,
731  net_def,
732  tensor_protos_map,
733  FLAGS_wipe_cache,
734  FLAGS_run_individual,
735  run_on_gpu,
736  FLAGS_text_output,
737  FLAGS_warmup,
738  FLAGS_iter,
739  num_blobs,
740  FLAGS_sleep_before_run,
741  FLAGS_sleep_between_iteration,
742  FLAGS_sleep_between_net_and_operator,
743  FLAGS_output,
744  FLAGS_output_folder);
745 
746  return 0;
747 }
748 
749 int main(int argc, char** argv) {
750  caffe2::GlobalInit(&argc, &argv);
751  benchmark(
752  argc,
753  argv,
754  FLAGS_backend,
755  FLAGS_init_net,
756  FLAGS_input_dims,
757  FLAGS_iter,
758  FLAGS_net,
759  FLAGS_output,
760  FLAGS_output_folder,
761  FLAGS_run_individual,
762  FLAGS_sleep_before_run,
763  FLAGS_sleep_between_iteration,
764  FLAGS_sleep_between_net_and_operator,
765  FLAGS_text_output,
766  FLAGS_warmup,
767  FLAGS_wipe_cache);
768 
769  return 0;
770 }
Blob is a general container that hosts a typed pointer.
Definition: blob.h:24
void Start()
Starts a timer.
Definition: timer.h:24
bool HasCudaGPU()
Check if the current running session has a cuda gpu present.
Definition: common_gpu.h:149
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
TensorDeserializer is the deserializer for Tensors.
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
Definition: blob.h:13
Definition: static.cpp:64
float MicroSeconds()
Returns the elapsed time in microseconds.
Definition: timer.h:36
bool GlobalInit(int *pargc, char ***pargv)
Initialize the global environment of caffe2.
Definition: init.cc:44
A simple timer object for measuring time.
Definition: timer.h:16
void SerializeBlob(const Blob &blob, const string &name, BlobSerializerBase::SerializationAcceptor acceptor, int chunk_size)
Serializes the given blob, if possible.