Caffe2 - C++ API
A deep learning, cross platform ML framework
speed_benchmark.cc
1 
17 #include <string>
18 
19 #include "caffe2/core/init.h"
20 #include "caffe2/core/logging.h"
21 #include "caffe2/core/operator.h"
22 #include "caffe2/proto/caffe2.pb.h"
23 #include "caffe2/utils/proto_utils.h"
24 #include "caffe2/utils/string_utils.h"
25 
26 CAFFE2_DEFINE_string(net, "", "The given net to benchmark.");
27 CAFFE2_DEFINE_string(
28  init_net,
29  "",
30  "The given net to initialize any parameters.");
31 CAFFE2_DEFINE_string(
32  input,
33  "",
34  "Input that is needed for running the network. If "
35  "multiple input needed, use comma separated string.");
36 CAFFE2_DEFINE_string(
37  input_file,
38  "",
39  "Input file that contain the serialized protobuf for "
40  "the input blobs. If multiple input needed, use comma "
41  "separated string. Must have the same number of items "
42  "as input does.");
43 CAFFE2_DEFINE_string(
44  input_dims,
45  "",
46  "Alternate to input_files, if all inputs are simple "
47  "float TensorCPUs, specify the dimension using comma "
48  "separated numbers. If multiple input needed, use "
49  "semicolon to separate the dimension of different "
50  "tensors.");
51 CAFFE2_DEFINE_string(
52  input_type,
53  "", "Input type (uint8_t/float)");
54 CAFFE2_DEFINE_string(
55  output,
56  "",
57  "Output that should be dumped after the execution "
58  "finishes. If multiple outputs are needed, use comma "
59  "separated string. If you want to dump everything, pass "
60  "'*' as the output value.");
61 CAFFE2_DEFINE_string(
62  output_folder,
63  "",
64  "The folder that the output should be written to. This "
65  "folder must already exist in the file system.");
66 CAFFE2_DEFINE_int(warmup, 0, "The number of iterations to warm up.");
67 CAFFE2_DEFINE_int(iter, 10, "The number of iterations to run.");
68 CAFFE2_DEFINE_bool(
69  run_individual,
70  false,
71  "Whether to benchmark individual operators.");
72 
73 CAFFE2_DEFINE_bool(force_engine, false, "Force engine field for all operators");
74 CAFFE2_DEFINE_string(engine, "", "Forced engine field value");
75 CAFFE2_DEFINE_bool(force_algo, false, "Force algo arg for all operators");
76 CAFFE2_DEFINE_string(algo, "", "Forced algo arg value");
77 
78 using std::string;
79 using std::unique_ptr;
80 using std::vector;
81 
82 int main(int argc, char** argv) {
83  caffe2::GlobalInit(&argc, &argv);
84  unique_ptr<caffe2::Workspace> workspace(new caffe2::Workspace());
85 
86  // Run initialization network.
87  caffe2::NetDef net_def;
88  CAFFE_ENFORCE(ReadProtoFromFile(caffe2::FLAGS_init_net, &net_def));
89  CAFFE_ENFORCE(workspace->RunNetOnce(net_def));
90 
91  // Load input.
92  if (caffe2::FLAGS_input.size()) {
93  vector<string> input_names = caffe2::split(',', caffe2::FLAGS_input);
94  if (caffe2::FLAGS_input_file.size()) {
95  vector<string> input_files = caffe2::split(',', caffe2::FLAGS_input_file);
96  CAFFE_ENFORCE_EQ(
97  input_names.size(),
98  input_files.size(),
99  "Input name and file should have the same number.");
100  for (int i = 0; i < input_names.size(); ++i) {
101  caffe2::BlobProto blob_proto;
102  CAFFE_ENFORCE(caffe2::ReadProtoFromFile(input_files[i], &blob_proto));
103  workspace->CreateBlob(input_names[i])->Deserialize(blob_proto);
104  }
105  } else if (caffe2::FLAGS_input_dims.size() || caffe2::FLAGS_input_type.size()) {
106  CAFFE_ENFORCE_NE(0, caffe2::FLAGS_input_dims.size(),
107  "Input dims must be specified when input tensors are used.");
108  CAFFE_ENFORCE_NE(0, caffe2::FLAGS_input_type.size(),
109  "Input type must be specified when input tensors are used.");
110 
111  vector<string> input_dims_list =
112  caffe2::split(';', caffe2::FLAGS_input_dims);
113  CAFFE_ENFORCE_EQ(
114  input_names.size(),
115  input_dims_list.size(),
116  "Input name and dims should have the same number of items.");
117  vector<string> input_type_list =
118  caffe2::split(';', caffe2::FLAGS_input_type);
119  CAFFE_ENFORCE_EQ(
120  input_names.size(),
121  input_type_list.size(),
122  "Input name and type should have the same number of items.");
123  for (size_t i = 0; i < input_names.size(); ++i) {
124  vector<string> input_dims_str = caffe2::split(',', input_dims_list[i]);
125  vector<int> input_dims;
126  for (const string& s : input_dims_str) {
127  input_dims.push_back(caffe2::stoi(s));
128  }
129  caffe2::Blob* blob = workspace->GetBlob(input_names[i]);
130  if (blob == nullptr) {
131  blob = workspace->CreateBlob(input_names[i]);
132  }
134  CHECK_NOTNULL(tensor);
135  tensor->Resize(input_dims);
136  if (input_type_list[i] == "uint8_t") {
137  tensor->mutable_data<uint8_t>();
138  } else if (input_type_list[i] == "float") {
139  tensor->mutable_data<float>();
140  } else {
141  CAFFE_THROW("Unsupported input type: ", input_type_list[i]);
142  }
143  }
144  } else {
145  CAFFE_THROW(
146  "You requested input tensors, but neither input_file nor "
147  "input_dims is set.");
148  }
149  }
150 
151  // Run main network.
152  CAFFE_ENFORCE(ReadProtoFromFile(caffe2::FLAGS_net, &net_def));
153  // force changing engine and algo
154  if (caffe2::FLAGS_force_engine) {
155  LOG(INFO) << "force engine be: " << caffe2::FLAGS_engine;
156  for (const auto& op : net_def.op()) {
157  const_cast<caffe2::OperatorDef*>(&op)->set_engine(caffe2::FLAGS_engine);
158  }
159  }
160  if (caffe2::FLAGS_force_algo) {
161  LOG(INFO) << "force algo be: " << caffe2::FLAGS_algo;
162  for (const auto& op : net_def.op()) {
163  caffe2::GetMutableArgument(
164  "algo", true, const_cast<caffe2::OperatorDef*>(&op))
165  ->set_s(caffe2::FLAGS_algo);
166  }
167  }
168  caffe2::NetBase* net = workspace->CreateNet(net_def);
169  CHECK_NOTNULL(net);
170  net->TEST_Benchmark(
171  caffe2::FLAGS_warmup, caffe2::FLAGS_iter, caffe2::FLAGS_run_individual);
172 
173  string output_prefix = caffe2::FLAGS_output_folder.size()
174  ? caffe2::FLAGS_output_folder + "/"
175  : "";
176  if (caffe2::FLAGS_output.size()) {
177  vector<string> output_names = caffe2::split(',', caffe2::FLAGS_output);
178  if (caffe2::FLAGS_output == "*") {
179  output_names = workspace->Blobs();
180  }
181  for (const string& name : output_names) {
182  CAFFE_ENFORCE(
183  workspace->HasBlob(name),
184  "You requested a non-existing blob: ",
185  name);
186  string serialized = workspace->GetBlob(name)->Serialize(name);
187  string output_filename = output_prefix + name;
188  caffe2::WriteStringToFile(serialized, output_filename.c_str());
189  }
190  }
191 
192  return 0;
193 }
Blob is a general container that hosts a typed pointer.
Definition: blob.h:25
bool GlobalInit(int *pargc, char ***pargv)
Initialize the global environment of caffe2.
Definition: init.cc:18
T * mutable_data()
Returns a typed pointer of the underlying storage.
Definition: tensor.h:578
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
Definition: workspace.h:47
void Resize(Ts...dim_source)
Resizes a tensor.
Definition: tensor.h:288
T * GetMutable(bool *is_new_object=nullptr)
Gets a mutable pointer to the stored object.
Definition: blob.h:101
virtual vector< float > TEST_Benchmark(const int, const int, const bool)
Benchmarks a network.
Definition: net.h:77