2 * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
20 #include <json/json.h>
25 // This function parses a json object and returns as a vector of integers
27 // [0, [1, 2, 3, 4], 3, 40, 4, []] in JSON
33 // } in std::unordered_map. Note that the value type is still Json::Value.
34 std::unordered_map<uint32_t, Json::Value> argArrayToMap(const Json::Value &jsonval)
36 if (!jsonval.isArray() || (jsonval.size() % 2 != 0))
38 std::cerr << "JSON argument must be an even-sized array in JSON\n";
42 std::unordered_map<uint32_t, Json::Value> ret;
43 for (uint32_t i = 0; i < jsonval.size(); i += 2)
45 if (!jsonval[i].isUInt())
47 std::cerr << "Key values(values in even indices) must be unsigned integers\n";
50 uint32_t key = jsonval[i].asUInt();
51 Json::Value val = jsonval[i + 1];
52 ret[key] = jsonval[i + 1];
57 // param shape_str is a form of, e.g., "[1, [2, 3], 3, []]"
58 void handleShapeParam(nnpkg_run::TensorShapeMap &shape_map, const std::string &shape_str)
62 if (!reader.parse(shape_str, root, false))
64 std::cerr << "Invalid JSON format for output_sizes \"" << shape_str << "\"\n";
68 auto arg_map = argArrayToMap(root);
69 for (auto &pair : arg_map)
71 uint32_t key = pair.first;
72 Json::Value &shape_json = pair.second;
73 if (!shape_json.isArray())
75 std::cerr << "All the values must be list: " << shape_str << "\n";
79 std::vector<int> shape;
80 for (auto &dim_json : shape_json)
82 if (!dim_json.isUInt())
84 std::cerr << "All the dims should be dim >= 0: " << shape_str << "\n";
88 shape.emplace_back(dim_json.asUInt64());
91 shape_map[key] = shape;
100 Args::Args(const int argc, char **argv)
106 void Args::Initialize(void)
109 po::options_description general("General options", 100);
112 general.add_options()
113 ("help,h", "Print available options")
114 ("version", "Print version and exit immediately")
115 ("nnpackage", po::value<std::string>()->required())
116 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
117 ("dump,d", po::value<std::string>()->default_value(""), "Output filename")
118 ("load,l", po::value<std::string>()->default_value(""), "Input filename")
120 ("output_sizes", po::value<std::string>(),
121 "The output buffer size in JSON 1D array\n"
122 "If not given, the model's output sizes are used\n"
123 "e.g. '[0, 40, 2, 80]' to set 0th tensor to 40 and 2nd tensor to 80.\n")
124 ("num_runs,r", po::value<int>()->default_value(1), "The number of runs")
125 ("warmup_runs,w", po::value<int>()->default_value(0), "The number of warmup runs")
126 ("run_delay,t", po::value<int>()->default_value(-1), "Delay time(ms) between runs (as default no delay")
127 ("gpumem_poll,g", po::value<bool>()->default_value(false), "Check gpu memory polling separately")
128 ("mem_poll,m", po::value<bool>()->default_value(false), "Check memory polling")
129 ("write_report,p", po::value<bool>()->default_value(false),
131 "{exec}-{nnpkg}-{backend}.csv will be generated.\n"
132 "e.g. nnpackage_run-UNIT_Add_000-acl_cl.csv.\n"
133 "{nnpkg} name may be changed to realpath if you use symbolic-link.")
134 ("shape_prepare", po::value<std::string>()->default_value("[]"),
135 "set shape of specified tensor before compilation\n"
136 "e.g. '[0, [1, 2], 2, []]' to set 0th tensor to [1, 2] and 2nd tensor to [].\n")
137 ("shape_run", po::value<std::string>()->default_value("[]"),
138 "set shape of specified tensor right before running\n"
139 "e.g. '[1, [1, 2]]` to set 1st tensor to [1, 2].\n")
140 ("verbose_level,v", po::value<int>()->default_value(0), "Verbose level\n"
141 "0: prints the only result. Messages btw run don't print\n"
142 "1: prints result and message btw run\n"
143 "2: prints all of messages to print\n")
147 _options.add(general);
148 _positional.add("nnpackage", 1);
151 void Args::Parse(const int argc, char **argv)
153 po::variables_map vm;
154 po::store(po::command_line_parser(argc, argv).options(_options).positional(_positional).run(),
158 auto conflicting_options = [&](const std::string &o1, const std::string &o2) {
159 if ((vm.count(o1) && !vm[o1].defaulted()) && (vm.count(o2) && !vm[o2].defaulted()))
161 throw boost::program_options::error(std::string("Two options '") + o1 + "' and '" + o2 +
162 "' cannot be given at once.");
167 if (vm.count("help"))
169 std::cout << "nnpackage_run\n\n";
170 std::cout << "Usage: " << argv[0] << " path to nnpackage root directory [<options>]\n\n";
171 std::cout << _options;
177 if (vm.count("version"))
179 _print_version = true;
186 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
187 if (vm.count("dump"))
189 _dump_filename = vm["dump"].as<std::string>();
192 if (vm.count("load"))
194 _load_filename = vm["load"].as<std::string>();
198 if (vm.count("nnpackage"))
200 _package_filename = vm["nnpackage"].as<std::string>();
202 if (_package_filename.empty())
204 // TODO Print usage instead of the below message
205 std::cerr << "Please specify nnpackage file. Run with `--help` for usage."
212 if (access(_package_filename.c_str(), F_OK) == -1)
214 std::cerr << "nnpackage not found: " << _package_filename << "\n";
219 if (vm.count("output_sizes"))
221 auto output_sizes_json_str = vm["output_sizes"].as<std::string>();
225 if (!reader.parse(output_sizes_json_str, root, false))
227 std::cerr << "Invalid JSON format for output_sizes \"" << output_sizes_json_str << "\"\n";
231 auto arg_map = argArrayToMap(root);
232 for (auto &pair : arg_map)
234 uint32_t key = pair.first;
235 Json::Value &val_json = pair.second;
236 if (!val_json.isUInt())
238 std::cerr << "All the values in `output_sizes` must be unsigned integers\n";
241 uint32_t val = val_json.asUInt();
242 _output_sizes[key] = val;
246 if (vm.count("num_runs"))
248 _num_runs = vm["num_runs"].as<int>();
251 if (vm.count("warmup_runs"))
253 _warmup_runs = vm["warmup_runs"].as<int>();
256 if (vm.count("run_delay"))
258 _run_delay = vm["run_delay"].as<int>();
261 if (vm.count("gpumem_poll"))
263 _gpumem_poll = vm["gpumem_poll"].as<bool>();
266 if (vm.count("mem_poll"))
268 _mem_poll = vm["mem_poll"].as<bool>();
269 // Instead of EXECUTE to avoid overhead, memory polling runs on WARMUP
270 if (_mem_poll && _warmup_runs == 0)
276 if (vm.count("write_report"))
278 _write_report = vm["write_report"].as<bool>();
281 if (vm.count("verbose_level"))
283 _verbose_level = vm["verbose_level"].as<int>();
286 catch (const std::bad_cast &e)
288 std::cerr << "error by bad cast" << e.what() << '\n';
292 if (vm.count("shape_prepare"))
294 std::string shape_str;
297 shape_str = vm["shape_prepare"].as<std::string>();
299 catch (const std::bad_cast &e)
301 std::cerr << "error by bad cast with '--shape_prepare' option" << e.what() << '\n';
306 handleShapeParam(_shape_prepare, shape_str);
308 catch (const std::exception &e)
310 std::cerr << "error with '--shape_prepare' option: " << shape_str << std::endl;
315 if (vm.count("shape_run"))
317 std::string shape_str;
320 shape_str = vm["shape_run"].as<std::string>();
322 catch (const std::bad_cast &e)
324 std::cerr << "error by bad cast with '--shape_run' option" << e.what() << '\n';
329 handleShapeParam(_shape_run, shape_str);
331 catch (const std::exception &e)
333 std::cerr << "error with '--shape_run' option: " << shape_str << std::endl;
339 } // end of namespace nnpkg_run