| 319 | } |
| 320 | |
| 321 | Status TimeMultipleRuns(double sleep_seconds, int num_runs, double max_time_s, |
| 322 | const std::vector<InputLayerInfo>& inputs, |
| 323 | const std::vector<string>& outputs, |
| 324 | const std::vector<string>& targets, Session* session, |
| 325 | StatSummarizer* stats, int64* total_time_us, |
| 326 | int64* actual_num_runs) { |
| 327 | *total_time_us = 0; |
| 328 | |
| 329 | LOG(INFO) << "Running benchmark for max " << num_runs << " iterations, max " |
| 330 | << max_time_s << " seconds " |
| 331 | << (stats != nullptr ? "with" : "without") |
| 332 | << " detailed stat logging, with " << sleep_seconds |
| 333 | << "s sleep between inferences"; |
| 334 | |
| 335 | Stat<int64> stat; |
| 336 | const bool until_max_time = num_runs <= 0; |
| 337 | for (int i = 0; until_max_time || i < num_runs; ++i) { |
| 338 | int64 time; |
| 339 | Status run_status = |
| 340 | RunBenchmark(inputs, outputs, targets, session, stats, &time); |
| 341 | stat.UpdateStat(time); |
| 342 | (*total_time_us) += time; |
| 343 | ++(*actual_num_runs); |
| 344 | |
| 345 | if (max_time_s > 0.0 && (*total_time_us / 1000000.0) > max_time_s) { |
| 346 | break; |
| 347 | } |
| 348 | |
| 349 | if (!run_status.ok()) { |
| 350 | LOG(INFO) << "Failed on run " << i; |
| 351 | return run_status; |
| 352 | } |
| 353 | |
| 354 | // If requested, sleep between runs for an arbitrary amount of time. |
| 355 | // This can be helpful to determine the effect of mobile processor |
| 356 | // scaling and thermal throttling. |
| 357 | if (sleep_seconds > 0.0) { |
| 358 | SleepSeconds(sleep_seconds); |
| 359 | } |
| 360 | } |
| 361 | std::stringstream stream; |
| 362 | stat.OutputToStream(&stream); |
| 363 | LOG(INFO) << stream.str() << std::endl; |
| 364 | |
| 365 | return Status::OK(); |
| 366 | } |
| 367 | |
| 368 | int Main(int argc, char** argv) { |
| 369 | string graph = "/data/local/tmp/tensorflow_inception_graph.pb"; |