5 #include "caffe2/core/blob_serialization.h" 6 #include "caffe2/core/init.h" 7 #include "caffe2/core/logging.h" 8 #include "caffe2/core/operator.h" 9 #include "caffe2/proto/caffe2.pb.h" 10 #include "caffe2/utils/proto_utils.h" 11 #include "caffe2/utils/string_utils.h" 13 #include "observers/observer_config.h" 18 "The backend to use when running the model. The allowed " 19 "backend choices are: builtin, default, nnpack, eigen, mkl");
23 "The given net to initialize any parameters.");
27 "Input that is needed for running the network. If " 28 "multiple input needed, use comma separated string.");
32 "Alternate to input_files, if all inputs are simple " 33 "float TensorCPUs, specify the dimension using comma " 34 "separated numbers. If multiple input needed, use " 35 "semicolon to separate the dimension of different " 40 "Input file that contain the serialized protobuf for " 41 "the input blobs. If multiple input needed, use comma " 42 "separated string. Must have the same number of items " 47 "Input type when specifying the input dimension." 48 "The supported types are float, uint8_t.");
49 CAFFE2_DEFINE_int(iter, 10,
"The number of iterations to run.");
50 CAFFE2_DEFINE_string(net,
"",
"The given net to benchmark.");
54 "Output that should be dumped after the execution " 55 "finishes. If multiple outputs are needed, use comma " 56 "separated string. If you want to dump everything, pass " 57 "'*' as the output value.");
61 "The folder that the output should be written to. This " 62 "folder must already exist in the file system.");
66 "Whether to benchmark individual operators.");
70 "Whether to write out output in text format for regression purpose.");
71 CAFFE2_DEFINE_int(warmup, 0,
"The number of iterations to warm up.");
74 using std::unique_ptr;
77 static void writeTextOutput(
79 const string& output_prefix,
81 string output_name = output_prefix +
"/" + name +
".txt";
83 caffe2::BlobProto blob_proto;
85 *tensor, output_name, blob_proto.mutable_tensor(), 0, tensor->
size());
86 blob_proto.set_name(output_name);
87 blob_proto.set_type(
"Tensor");
88 CAFFE_ENFORCE(blob_proto.has_tensor());
89 caffe2::TensorProto tensor_proto = blob_proto.tensor();
91 switch (tensor_proto.data_type()) {
92 case caffe2::TensorProto::FLOAT: {
94 tensor_proto.float_data().begin(),
95 tensor_proto.float_data().end(),
96 std::back_inserter(data));
99 case caffe2::TensorProto::INT32: {
101 tensor_proto.int32_data().begin(),
102 tensor_proto.int32_data().end(),
103 std::back_inserter(data));
107 CAFFE_THROW(
"Unimplemented Blob type.");
109 std::ofstream output_file(output_name);
110 std::ostream_iterator<float> output_iterator(output_file,
"\n");
111 std::copy(data.begin(), data.end(), output_iterator);
114 int main(
int argc,
char** argv) {
120 caffe2::NetDef init_net_def;
121 CAFFE_ENFORCE(ReadProtoFromFile(caffe2::FLAGS_init_net, &init_net_def));
122 CAFFE_ENFORCE(workspace->RunNetOnce(init_net_def));
125 if (caffe2::FLAGS_input.size()) {
126 vector<string> input_names = caffe2::split(
',', caffe2::FLAGS_input);
127 if (caffe2::FLAGS_input_file.size()) {
128 vector<string> input_files = caffe2::split(
',', caffe2::FLAGS_input_file);
132 "Input name and file should have the same number.");
133 for (
int i = 0; i < input_names.size(); ++i) {
134 caffe2::BlobProto blob_proto;
135 CAFFE_ENFORCE(caffe2::ReadProtoFromFile(input_files[i], &blob_proto));
136 workspace->CreateBlob(input_names[i])->Deserialize(blob_proto);
138 }
else if (caffe2::FLAGS_input_dims.size()) {
139 vector<string> input_dims_list =
140 caffe2::split(
';', caffe2::FLAGS_input_dims);
143 input_dims_list.size(),
144 "Input name and dims should have the same number of items.");
145 for (
int i = 0; i < input_names.size(); ++i) {
146 vector<string> input_dims_str = caffe2::split(
',', input_dims_list[i]);
147 vector<int> input_dims;
148 for (
const string& s : input_dims_str) {
149 input_dims.push_back(caffe2::stoi(s));
151 if (!workspace->HasBlob(input_names[i])) {
152 workspace->CreateBlob(input_names[i]);
156 tensor->
Resize(input_dims);
157 if (caffe2::FLAGS_input_type ==
"float") {
161 caffe2::FLAGS_input_type ==
"uint8_t",
162 "Only supported input types are: float, uint8_t");
168 "You requested input tensors, but neither input_file nor " 169 "input_dims is set.");
174 caffe2::NetDef net_def;
175 CAFFE_ENFORCE(ReadProtoFromFile(caffe2::FLAGS_net, &net_def));
176 if (caffe2::FLAGS_backend !=
"builtin") {
177 std::string engine = caffe2::FLAGS_backend ==
"nnpack" 179 : caffe2::FLAGS_backend ==
"eigen" ?
"EIGEN" 180 : caffe2::FLAGS_backend ==
"mkl" 182 : caffe2::FLAGS_backend ==
"default" ?
"" :
"NONE";
183 CAFFE_ENFORCE(engine !=
"NONE",
"Backend is not supported");
184 for (
int i = 0; i < net_def.op_size(); i++) {
185 caffe2::OperatorDef* op_def = net_def.mutable_op(i);
186 op_def->set_engine(engine);
193 LOG(INFO) <<
"Starting benchmark.";
194 caffe2::ObserverConfig::initSampleRate(
195 1, 1, 1, caffe2::FLAGS_run_individual, caffe2::FLAGS_warmup);
196 LOG(INFO) <<
"Running warmup runs.";
197 for (
int i = 0; i < caffe2::FLAGS_warmup; ++i) {
198 CAFFE_ENFORCE(net->Run(),
"Warmup run ", i,
" has failed.");
201 LOG(INFO) <<
"Main runs.";
203 caffe2::FLAGS_iter >= 0,
204 "Number of main runs should be non negative, provided ",
207 for (
int i = 0; i < caffe2::FLAGS_iter; ++i) {
208 caffe2::ObserverConfig::initSampleRate(1, 1, 1, 0, caffe2::FLAGS_warmup);
209 CAFFE_ENFORCE(net->Run(),
"Main run ", i,
" has failed.");
210 if (caffe2::FLAGS_run_individual) {
211 caffe2::ObserverConfig::initSampleRate(1, 1, 1, 1, caffe2::FLAGS_warmup);
212 CAFFE_ENFORCE(net->Run(),
"Main run ", i,
" with operator has failed.");
216 string output_prefix = caffe2::FLAGS_output_folder.size()
217 ? caffe2::FLAGS_output_folder +
"/" 219 if (caffe2::FLAGS_output.size()) {
220 vector<string> output_names = caffe2::split(
',', caffe2::FLAGS_output);
221 if (caffe2::FLAGS_output ==
"*") {
222 output_names = workspace->Blobs();
224 for (
const string& name : output_names) {
226 workspace->HasBlob(name),
227 "You requested a non-existing blob: ",
229 if (caffe2::FLAGS_text_output) {
231 writeTextOutput(blob, output_prefix, name);
233 string serialized = workspace->GetBlob(name)->Serialize(name);
234 string output_filename = output_prefix + name;
235 caffe2::WriteStringToFile(serialized, output_filename.c_str());
bool GlobalInit(int *pargc, char ***pargv)
Initialize the global environment of caffe2.
TensorSerializer is the serializer for Tensors.
TIndex size() const
Returns the size (i.e.
T * mutable_data()
Returns a typed pointer of the underlying storage.
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
void Serialize(const Blob &blob, const string &name, SerializationAcceptor acceptor) override
Serializes a Blob.
void Resize(Ts...dim_source)
Resizes a tensor.
void ShowLogInfoToStderr()
A utility to allow one to show log info to stderr after the program starts.