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.
21 #include <json/json.h>
26 // This function parses a json object and returns as a vector of integers
28 // [0, [1, 2, 3, 4], 3, 40, 4, []] in JSON
34 // } in std::unordered_map. Note that the value type is still Json::Value.
35 std::unordered_map<uint32_t, Json::Value> argArrayToMap(const Json::Value &jsonval)
37 if (!jsonval.isArray() || (jsonval.size() % 2 != 0))
39 std::cerr << "JSON argument must be an even-sized array in JSON\n";
43 std::unordered_map<uint32_t, Json::Value> ret;
44 for (uint32_t i = 0; i < jsonval.size(); i += 2)
46 if (!jsonval[i].isUInt())
48 std::cerr << "Key values(values in even indices) must be unsigned integers\n";
51 uint32_t key = jsonval[i].asUInt();
52 Json::Value val = jsonval[i + 1];
53 ret[key] = jsonval[i + 1];
58 // param shape_str is a form of, e.g., "[1, [2, 3], 3, []]"
59 void handleShapeParam(nnpkg_run::TensorShapeMap &shape_map, const std::string &shape_str)
63 if (!reader.parse(shape_str, root, false))
65 std::cerr << "Invalid JSON format for output_sizes \"" << shape_str << "\"\n";
69 auto arg_map = argArrayToMap(root);
70 for (auto &pair : arg_map)
72 uint32_t key = pair.first;
73 Json::Value &shape_json = pair.second;
74 if (!shape_json.isArray())
76 std::cerr << "All the values must be list: " << shape_str << "\n";
80 std::vector<int> shape;
81 for (auto &dim_json : shape_json)
83 if (!dim_json.isUInt())
85 std::cerr << "All the dims should be dim >= 0: " << shape_str << "\n";
89 shape.emplace_back(dim_json.asUInt64());
92 shape_map[key] = shape;
101 Args::Args(const int argc, char **argv)
107 void Args::Initialize(void)
109 auto process_nnpackage = [&](const std::string &package_filename) {
110 _package_filename = package_filename;
112 std::cerr << "Package Filename " << _package_filename << std::endl;
113 if (_package_filename.empty())
115 // TODO Print usage instead of the below message
116 std::cerr << "Please specify nnpackage file. Run with `--help` for usage."
123 if (access(_package_filename.c_str(), F_OK) == -1)
125 std::cerr << "nnpackage not found: " << _package_filename << "\n";
130 auto process_output_sizes = [&](const std::string &output_sizes_json_str) {
133 if (!reader.parse(output_sizes_json_str, root, false))
135 std::cerr << "Invalid JSON format for output_sizes \"" << output_sizes_json_str << "\"\n";
139 auto arg_map = argArrayToMap(root);
140 for (auto &pair : arg_map)
142 uint32_t key = pair.first;
143 Json::Value &val_json = pair.second;
144 if (!val_json.isUInt())
146 std::cerr << "All the values in `output_sizes` must be unsigned integers\n";
149 uint32_t val = val_json.asUInt();
150 _output_sizes[key] = val;
154 auto process_shape_prepare = [&](const std::string &shape_str) {
157 handleShapeParam(_shape_prepare, shape_str);
159 catch (const std::exception &e)
161 std::cerr << "error with '--shape_prepare' option: " << shape_str << std::endl;
166 auto process_shape_run = [&](const std::string &shape_str) {
169 handleShapeParam(_shape_run, shape_str);
171 catch (const std::exception &e)
173 std::cerr << "error with '--shape_run' option: " << shape_str << std::endl;
179 po::options_description general("General options", 100);
182 general.add_options()
183 ("help,h", "Print available options")
184 ("version", "Print version and exit immediately")
185 ("nnpackage", po::value<std::string>()->required()->notifier(process_nnpackage))
186 #if defined(ONERT_HAVE_HDF5) && ONERT_HAVE_HDF5 == 1
187 ("dump,d", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _dump_filename = v; }), "Output filename")
188 ("load,l", po::value<std::string>()->default_value("")->notifier([&](const auto &v) { _load_filename = v; }), "Input filename")
190 ("output_sizes", po::value<std::string>()->notifier(process_output_sizes),
191 "The output buffer size in JSON 1D array\n"
192 "If not given, the model's output sizes are used\n"
193 "e.g. '[0, 40, 2, 80]' to set 0th tensor to 40 and 2nd tensor to 80.\n")
194 ("num_runs,r", po::value<int>()->default_value(1)->notifier([&](const auto &v) { _num_runs = v; }), "The number of runs")
195 ("warmup_runs,w", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _warmup_runs = v; }), "The number of warmup runs")
196 ("run_delay,t", po::value<int>()->default_value(-1)->notifier([&](const auto &v) { _run_delay = v; }), "Delay time(ms) between runs (as default no delay")
197 ("gpumem_poll,g", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _gpumem_poll = v; }), "Check gpu memory polling separately")
198 ("mem_poll,m", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _mem_poll = v; }), "Check memory polling")
199 ("write_report,p", po::value<bool>()->default_value(false)->notifier([&](const auto &v) { _write_report = v; }),
201 "{exec}-{nnpkg}-{backend}.csv will be generated.\n"
202 "e.g. nnpackage_run-UNIT_Add_000-acl_cl.csv.\n"
203 "{nnpkg} name may be changed to realpath if you use symbolic-link.")
204 ("shape_prepare", po::value<std::string>()->default_value("[]")->notifier(process_shape_prepare),
205 "set shape of specified tensor before compilation\n"
206 "e.g. '[0, [1, 2], 2, []]' to set 0th tensor to [1, 2] and 2nd tensor to [].\n")
207 ("shape_run", po::value<std::string>()->default_value("[]")->notifier(process_shape_run),
208 "set shape of specified tensor right before running\n"
209 "e.g. '[1, [1, 2]]` to set 1st tensor to [1, 2].\n")
210 ("verbose_level,v", po::value<int>()->default_value(0)->notifier([&](const auto &v) { _verbose_level = v; }),
212 "0: prints the only result. Messages btw run don't print\n"
213 "1: prints result and message btw run\n"
214 "2: prints all of messages to print\n")
218 _options.add(general);
219 _positional.add("nnpackage", 1);
222 void Args::Parse(const int argc, char **argv)
224 po::variables_map vm;
225 po::store(po::command_line_parser(argc, argv).options(_options).positional(_positional).run(),
229 auto conflicting_options = [&](const std::string &o1, const std::string &o2) {
230 if ((vm.count(o1) && !vm[o1].defaulted()) && (vm.count(o2) && !vm[o2].defaulted()))
232 throw boost::program_options::error(std::string("Two options '") + o1 + "' and '" + o2 +
233 "' cannot be given at once.");
238 if (vm.count("help"))
240 std::cout << "nnpackage_run\n\n";
241 std::cout << "Usage: " << argv[0] << " path to nnpackage root directory [<options>]\n\n";
242 std::cout << _options;
248 if (vm.count("version"))
250 _print_version = true;
258 catch (const std::bad_cast &e)
260 std::cerr << "Bad cast error - " << e.what() << '\n';
264 // This must be run after `notify` as `_warm_up_runs` must have been processed before.
265 if (vm.count("mem_poll"))
267 // Instead of EXECUTE to avoid overhead, memory polling runs on WARMUP
268 if (_mem_poll && _warmup_runs == 0)
275 } // end of namespace nnpkg_run