19 #include "caffe2/core/blob_serialization.h" 20 #include "caffe2/core/init.h" 21 #include "caffe2/core/logging.h" 22 #include "caffe2/core/operator.h" 23 #include "caffe2/core/tensor_int8.h" 24 #ifdef CAFFE2_OPTIMIZER 25 #include "caffe2/opt/optimizer.h" 27 #include "caffe2/proto/caffe2_pb.h" 28 #include "caffe2/utils/proto_utils.h" 29 #include "caffe2/utils/string_utils.h" 31 C10_DEFINE_string(net,
"",
"The given net to benchmark.");
32 C10_DEFINE_string(init_net,
"",
"The given net to initialize any parameters.");
36 "Input that is needed for running the network. If " 37 "multiple input needed, use comma separated string.");
41 "Input file that contain the serialized protobuf for " 42 "the input blobs. If multiple input needed, use comma " 43 "separated string. Must have the same number of items " 48 "Alternate to input_files, if all inputs are simple " 49 "float TensorCPUs, specify the dimension using comma " 50 "separated numbers. If multiple input needed, use " 51 "semicolon to separate the dimension of different " 53 C10_DEFINE_string(input_type,
"",
"Input type (uint8_t/float)");
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.");
64 "The folder that the output should be written to. This " 65 "folder must already exist in the file system.");
66 C10_DEFINE_int(warmup, 0,
"The number of iterations to warm up.");
67 C10_DEFINE_int(iter, 10,
"The number of iterations to run.");
68 C10_DEFINE_int(opt, 0,
"The level of optimization to run automatically.");
72 "Whether to benchmark individual operators.");
74 C10_DEFINE_bool(force_engine,
false,
"Force engine field for all operators");
75 C10_DEFINE_string(engine,
"",
"Forced engine field value");
76 C10_DEFINE_bool(force_algo,
false,
"Force algo arg for all operators");
77 C10_DEFINE_string(algo,
"",
"Forced algo arg value");
80 using std::unique_ptr;
83 int main(
int argc,
char** argv) {
88 caffe2::NetDef net_def;
89 CAFFE_ENFORCE(ReadProtoFromFile(FLAGS_init_net, &net_def));
90 CAFFE_ENFORCE(workspace->RunNetOnce(net_def));
93 if (FLAGS_input.size()) {
94 vector<string> input_names = caffe2::split(
',', FLAGS_input);
95 if (FLAGS_input_file.size()) {
96 vector<string> input_files = caffe2::split(
',', FLAGS_input_file);
100 "Input name and file should have the same number.");
101 for (
int i = 0; i < input_names.size(); ++i) {
102 caffe2::BlobProto blob_proto;
103 CAFFE_ENFORCE(caffe2::ReadProtoFromFile(input_files[i], &blob_proto));
106 }
else if (FLAGS_input_dims.size() || FLAGS_input_type.size()) {
108 FLAGS_input_dims.size(),
110 "Input dims must be specified when input tensors are used.");
112 FLAGS_input_type.size(),
114 "Input type must be specified when input tensors are used.");
116 vector<string> input_dims_list = caffe2::split(
';', FLAGS_input_dims);
119 input_dims_list.size(),
120 "Input name and dims should have the same number of items.");
121 vector<string> input_type_list = caffe2::split(
';', FLAGS_input_type);
124 input_type_list.size(),
125 "Input name and type should have the same number of items.");
126 for (
size_t i = 0; i < input_names.size(); ++i) {
127 vector<string> input_dims_str = caffe2::split(
',', input_dims_list[i]);
128 vector<int> input_dims;
129 for (
const string& s : input_dims_str) {
130 input_dims.push_back(c10::stoi(s));
132 caffe2::Blob* blob = workspace->GetBlob(input_names[i]);
133 if (blob ==
nullptr) {
134 blob = workspace->CreateBlob(input_names[i]);
136 if (input_type_list[i] ==
"uint8_t") {
139 CHECK_NOTNULL(tensor);
140 tensor->t.Resize(input_dims);
141 tensor->t.mutable_data<uint8_t>();
142 }
else if (input_type_list[i] ==
"float") {
144 CHECK_NOTNULL(tensor);
145 tensor->Resize(input_dims);
146 tensor->mutable_data<
float>();
148 CAFFE_THROW(
"Unsupported input type: ", input_type_list[i]);
153 "You requested input tensors, but neither input_file nor " 154 "input_dims is set.");
159 CAFFE_ENFORCE(ReadProtoFromFile(FLAGS_net, &net_def));
160 if (!net_def.has_name()) {
161 net_def.set_name(
"benchmark");
164 if (FLAGS_force_engine) {
165 LOG(INFO) <<
"force engine be: " << FLAGS_engine;
166 for (
const auto& op : net_def.op()) {
167 const_cast<caffe2::OperatorDef*
>(&op)->set_engine(FLAGS_engine);
170 if (FLAGS_force_algo) {
171 LOG(INFO) <<
"force algo be: " << FLAGS_algo;
172 for (
const auto& op : net_def.op()) {
173 caffe2::GetMutableArgument(
174 "algo",
true, const_cast<caffe2::OperatorDef*>(&op))
179 #ifdef CAFFE2_OPTIMIZER 180 net_def = caffe2::opt::optimize(net_def, workspace.get(), FLAGS_opt);
182 LOG(WARNING) <<
"Caffe2 not compiled with optimization passes.";
188 CAFFE_ENFORCE(net->Run());
189 net->
TEST_Benchmark(FLAGS_warmup, FLAGS_iter, FLAGS_run_individual);
191 string output_prefix =
192 FLAGS_output_folder.size() ? FLAGS_output_folder +
"/" :
"";
193 if (FLAGS_output.size()) {
194 vector<string> output_names = caffe2::split(
',', FLAGS_output);
195 if (FLAGS_output ==
"*") {
196 output_names = workspace->Blobs();
198 for (
const string& name : output_names) {
200 workspace->HasBlob(name),
201 "You requested a non-existing blob: ",
203 string serialized =
SerializeBlob(*workspace->GetBlob(name), name);
204 string output_filename = output_prefix + name;
205 caffe2::WriteStringToFile(serialized, output_filename.c_str());
virtual vector< float > TEST_Benchmark(const int, const int, const bool)
Benchmarks a network.
Blob is a general container that hosts a typed pointer.
void DeserializeBlob(const string &content, Blob *result)
Deserializes from a string containing either BlobProto or TensorProto.
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
T * GetMutable()
Gets a mutable pointer to the stored object.
bool GlobalInit(int *pargc, char ***pargv)
Initialize the global environment of caffe2.
void SerializeBlob(const Blob &blob, const string &name, BlobSerializerBase::SerializationAcceptor acceptor, int chunk_size)
Serializes the given blob, if possible.