From 2e5a473de1e0845cdaf8dc6dda3151059aa3333e Mon Sep 17 00:00:00 2001 From: Megvii Engine Team Date: Mon, 21 Jun 2021 20:40:26 +0800 Subject: [PATCH] feat(lar): support --verbose GitOrigin-RevId: f690193b754a4b8f3322ec2129ba3259b8bedf90 --- sdk/load-and-run/BUILD | 2 + sdk/load-and-run/src/mgblar.cpp | 47 +++++++++++++++ sdk/load-and-run/src/text_table.cpp | 108 +++++++++++++++++++++++++++++++++ sdk/load-and-run/src/text_table.h | 117 ++++++++++++++++++++++++++++++++++++ 4 files changed, 274 insertions(+) create mode 100644 sdk/load-and-run/src/text_table.cpp create mode 100644 sdk/load-and-run/src/text_table.h diff --git a/sdk/load-and-run/BUILD b/sdk/load-and-run/BUILD index fefd74cd..54b98e68 100644 --- a/sdk/load-and-run/BUILD +++ b/sdk/load-and-run/BUILD @@ -5,11 +5,13 @@ cc_library( "src/infile_persistent_cache.cpp", "src/mgblar.cpp", "src/json_loader.cpp", + "src/text_table.cpp", ], hdrs = [ "src/infile_persistent_cache.h", "src/mgblar.h", "src/json_loader.h", + "src/text_table.h", "src/npy.h", ], features = if_opt([ diff --git a/sdk/load-and-run/src/mgblar.cpp b/sdk/load-and-run/src/mgblar.cpp index 8f5cbca0..86d2332c 100644 --- a/sdk/load-and-run/src/mgblar.cpp +++ b/sdk/load-and-run/src/mgblar.cpp @@ -13,6 +13,7 @@ #include "./infile_persistent_cache.h" #include "./json_loader.h" #include "./npy.h" +#include "./text_table.h" #include "megbrain/comp_node_env.h" #include "megbrain/gopt/inference.h" @@ -91,6 +92,8 @@ R"__usage__( param.json --data bbox:bbox.npy@batchid:b.npy --data rect:[0,0,227,227]; batchid:0,1,2,3. --io-dump or --bin-io-dump should be enabled at the same time. + --verbose + Format and display model input/output tensor info. --io-dump | --bin-io-dump Dump input/output values of all internal variables to output file or directory, in text or binary format. The binary file can be parsed by @@ -526,6 +529,7 @@ struct Args { COprArgs c_opr_args; + bool show_verbose = false; bool disable_assert_throw = false; bool share_param_mem = false; #if MGB_ENABLE_FASTRUN @@ -637,6 +641,36 @@ public: } }; +void format_and_print(const std::string& tablename, const Args& env) { + auto table = mgb::TextTable(tablename); + table.padding(1); + table.align(mgb::TextTable::Align::Mid) + .add("type") + .add("name") + .add("shape") + .eor(); + + for (auto &&i: env.load_ret.tensor_map) { + table.align(mgb::TextTable::Align::Mid) + .add("INPUT") + .add(i.first) + .add(i.second->shape().to_string()) + .eor(); + } + + for (auto&& i : env.load_ret.output_var_list) { + table.align(mgb::TextTable::Align::Mid) + .add("OUTPUT") + .add(i.node()->name()) + .add(i.shape().to_string()) + .eor(); + } + + std::stringstream ss; + ss << table; + printf("%s\n\n", ss.str().c_str()); +} + void run_test_st(Args &env) { std::unique_ptr inp_file; @@ -675,6 +709,10 @@ void run_test_st(Args &env) { // compile function to compute all outputs ComputingGraph::OutputSpec out_spec; std::string output_names; + + if (env.show_verbose) { + format_and_print("Original Model Info", env); + } OutputDumper output_dumper(env); for (auto&& i : env.load_ret.output_var_list) { @@ -987,6 +1025,10 @@ void run_test_st(Args &env) { TensorRTEngineCache::inst().dump_cache(); } #endif + + if (env.show_verbose) { + format_and_print("Runtime Model Info", env); + } } } // anonymous namespace @@ -1217,6 +1259,11 @@ Args Args::from_argv(int argc, char **argv) { } continue; } + if (!strcmp(argv[i], "--verbose")) { + ++i; + ret.show_verbose = true; + continue; + } if (!strcmp(argv[i], "--io-dump")) { mgb_log_warn("enable opr io dump"); ++ i; diff --git a/sdk/load-and-run/src/text_table.cpp b/sdk/load-and-run/src/text_table.cpp new file mode 100644 index 00000000..e3e8e9a6 --- /dev/null +++ b/sdk/load-and-run/src/text_table.cpp @@ -0,0 +1,108 @@ +/** + * \file sdk/load-and-run/src/text_table.cpp + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ + +#include "text_table.h" + +using namespace mgb; + +namespace { +inline void mid(std::ostream& os, const std::string& str, size_t max_w) { + size_t l = (max_w - str.length()) / 2 + str.length(); + size_t r = max_w - l; + os << std::setw(l) << std::right << str; + if (r > 0) os << std::setw(r) << ' '; +} +inline size_t char_length(char c) { return c ? 1 : 0; } +} // namespace + +void TextTable::adjuster_last_row() { + if (m_rows.empty()) return; + auto& row = m_rows.back(); + if (row.params.horizontal == 0 or row.params.vertical == 0) { + row.params.corner = 0; + } + if (row.params.horizontal != 0 && row.params.vertical != 0 && + row.params.corner == 0) { + row.params.corner = row.params.horizontal; + } +} + +void TextTable::show(std::ostream& os) { + if (m_rows.empty()) return; + auto& last_row = m_rows.front(); + bool first = true; + for (auto& row : m_rows) { + auto& lrow = + (last_row.values.size() * char_length(last_row.params.horizontal)) > + (row.values.size() * char_length(row.params.horizontal)) + ? last_row + : row; + // line before row + if (lrow.params.horizontal) { + if (not first) os << std::endl; + os << m_prefix; + if (lrow.params.corner) os << lrow.params.corner; + size_t skip_size = 0; + // table name + if (first) { + os << m_name; + skip_size = m_name.length(); + } + for (size_t i = 0; i < lrow.values.size(); ++i) { + auto max_w = m_cols_max_w.at(i) + m_padding * 2; + if (max_w + char_length(lrow.params.corner) <= skip_size) { + skip_size = + skip_size - max_w - char_length(lrow.params.corner); + continue; + } + size_t rest = + max_w + char_length(lrow.params.corner) - skip_size; + skip_size = 0; + if (rest > char_length(lrow.params.corner)) { + os << std::string(rest - char_length(lrow.params.corner), + lrow.params.horizontal); + rest = char_length(lrow.params.corner); + } + if (rest > 0 && lrow.params.corner) os << lrow.params.corner; + } + } else if (first) { + os << m_prefix << ' ' << m_name; + } + first = false; + os << std::endl << m_prefix; + if (row.params.vertical) os << row.params.vertical; + // row + for (size_t i = 0; i < row.values.size(); ++i) { + auto& str = row.values.at(i); + auto max_w = m_cols_max_w.at(i) + 2 * m_padding; + if (row.params.align == Align::Mid) { + mid(os, str, max_w); + } else if (row.params.align == Align::Left) { + os << std::setw(max_w) << std::left << str; + } else { + os << std::setw(max_w) << std::right << str; + } + if (row.params.vertical) os << row.params.vertical; + } + last_row = row; + } + if (last_row.params.horizontal) { + os << std::endl << m_prefix; + if (last_row.params.corner) os << last_row.params.corner; + for (size_t i = 0; i < last_row.values.size(); ++i) { + auto max_w = m_cols_max_w.at(i); + std::string tmp(max_w + m_padding * 2, last_row.params.horizontal); + os << tmp; + if (last_row.params.corner) os << last_row.params.corner; + } + } +} \ No newline at end of file diff --git a/sdk/load-and-run/src/text_table.h b/sdk/load-and-run/src/text_table.h new file mode 100644 index 00000000..ce7a172a --- /dev/null +++ b/sdk/load-and-run/src/text_table.h @@ -0,0 +1,117 @@ +/** + * \file sdk/load-and-run/src/text_table.h + * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") + * + * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "megbrain/common.h" + +namespace mgb +{ + +class TextTable { +public: + enum Level { Summary, Detail }; + enum class Align : int { Left, Right, Mid }; + explicit TextTable(const std::string& table_name) : m_name(table_name) {} + TextTable& horizontal(char c) { + m_row.params.horizontal = c; + return *this; + } + TextTable& vertical(char c) { + m_row.params.vertical = c; + return *this; + } + TextTable& corner(char c) { + m_row.params.corner = c; + return *this; + } + TextTable& align(Align v) { + m_row.params.align = v; + return *this; + } + TextTable& padding(size_t w) { + m_padding = w; + return *this; + } + TextTable& prefix(const std::string& str) { + m_prefix = str; + return *this; + } + + template + TextTable& add(const T& value) { + if constexpr (std::is_floating_point::value) { + std::stringstream ss; + ss << std::setiosflags(std::ios::fixed) << std::setprecision(2); + ss << value; + m_row.values.emplace_back(ss.str()); + } else if constexpr (std::is_integral::value) { + m_row.values.emplace_back(std::to_string(value)); + } else { + m_row.values.emplace_back(value); + } + if (m_cols_max_w.size() < m_row.values.size()) { + m_cols_max_w.emplace_back(m_row.values.back().length()); + } else { + mgb_assert(m_row.values.size() >= 1); + size_t i = m_row.values.size() - 1; + m_cols_max_w[i] = + std::max(m_cols_max_w[i], m_row.values.back().length()); + } + return *this; + } + + void eor() { + m_rows.emplace_back(m_row); + adjuster_last_row(); + m_row.values.clear(); + } + + void reset() { + m_row = {}; + m_cols_max_w.clear(); + m_padding = 0; + m_rows.clear(); + } + + void show(std::ostream& os); + +private: + void adjuster_last_row(); + std::string m_name; + std::vector m_cols_max_w; + size_t m_padding = 0; + std::string m_prefix = ""; + struct Row { + std::vector values; + struct Params { + Align align = Align::Left; + char horizontal = '-', vertical = '|', corner = '+'; + } params; + }; + std::vector m_rows; + Row m_row; +}; + +inline std::ostream& operator<<(std::ostream& stream, TextTable& table) { + table.show(stream); + return stream; +} + +} // namespace mgb \ No newline at end of file