aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/tools/tfprof/internal
diff options
context:
space:
mode:
Diffstat (limited to 'tensorflow/tools/tfprof/internal')
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/BUILD9
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h24
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/checker.h24
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h5
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/internal_checker_runner_dummy.cc6
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/operation_checker.h19
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/tfprof_advisor.h47
-rw-r--r--tensorflow/tools/tfprof/internal/advisor/tfprof_advisor_test.cc46
-rw-r--r--tensorflow/tools/tfprof/internal/print_model_analysis.cc19
-rw-r--r--tensorflow/tools/tfprof/internal/print_model_analysis.h2
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_graph.h4
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_op.cc11
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_op.h6
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_options.h4
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_show.cc14
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_show.h13
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_show_multi.cc19
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_show_multi.h16
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_show_test.cc1
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_stats.cc77
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_stats.h22
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_stats_test.cc1
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_tensor_test.cc1
-rw-r--r--tensorflow/tools/tfprof/internal/tfprof_timeline_test.cc1
24 files changed, 253 insertions, 138 deletions
diff --git a/tensorflow/tools/tfprof/internal/advisor/BUILD b/tensorflow/tools/tfprof/internal/advisor/BUILD
index e4bd0f0015..629322373a 100644
--- a/tensorflow/tools/tfprof/internal/advisor/BUILD
+++ b/tensorflow/tools/tfprof/internal/advisor/BUILD
@@ -45,11 +45,20 @@ cc_library(
)
cc_library(
+ name = "expensive_operation_checker",
+ hdrs = ["expensive_operation_checker.h"],
+ deps = [
+ ":checker",
+ ],
+)
+
+cc_library(
name = "tfprof_advisor",
hdrs = ["tfprof_advisor.h"],
deps = [
":accelerator_utilization_checker",
":checker",
+ ":expensive_operation_checker",
":internal_checker_runner_dummy",
":operation_checker",
],
diff --git a/tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h b/tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h
index fb7f65d7dc..074b8e57b0 100644
--- a/tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h
+++ b/tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h
@@ -33,10 +33,11 @@ struct ExecStats {
class AcceleratorUtilizationChecker : public Checker {
public:
- string name() override { return "AcceleratorUtilizationChecker"; }
+ string name() const override { return kCheckers[0]; }
private:
- std::vector<string> Check(const TFStats* stats) override {
+ AdviceProto::Checker Check(const AdvisorOptionsProto::CheckerOption& options,
+ const TFStats* stats) override {
if (!stats) {
fprintf(stderr, "Missing profiles (e.g. graph, run_meta). Skip %s\n",
name().c_str());
@@ -48,24 +49,21 @@ class AcceleratorUtilizationChecker : public Checker {
return CheckInternal();
}
- std::vector<string> CheckInternal() {
+ AdviceProto::Checker CheckInternal() {
for (const auto& s : accelerator_exec_stats_) {
const ExecStats& stat = s.second;
int64 total_micros = stat.end_micros - stat.start_micros;
if (total_micros <= 0) continue;
double utilization = 1.0 * stat.exec_micros / total_micros;
if (utilization >= 0.5) {
- reports_.push_back(strings::Printf("%s: device: %s utilization: %.2f",
- kLevel[0], s.first.c_str(),
- utilization));
+ reports_.add_reports(strings::Printf("device: %s utilization: %.2f",
+ s.first.c_str(), utilization));
} else if (utilization < 0.5 && utilization > 0.2) {
- reports_.push_back(
- strings::Printf("%s: device: %s low utilization: %.2f", kLevel[1],
- s.first.c_str(), utilization));
+ reports_.add_reports(strings::Printf("device: %s low utilization: %.2f",
+ s.first.c_str(), utilization));
} else if (utilization <= 0.2) {
- reports_.push_back(
- strings::Printf("%s: device: %s low utilization: %.2f", kLevel[2],
- s.first.c_str(), utilization));
+ reports_.add_reports(strings::Printf("device: %s low utilization: %.2f",
+ s.first.c_str(), utilization));
}
}
return reports_;
@@ -102,7 +100,7 @@ class AcceleratorUtilizationChecker : public Checker {
std::map<string, ExecStats> accelerator_exec_stats_;
std::map<string, int64> ps_placement_;
- std::vector<string> reports_;
+ AdviceProto::Checker reports_;
};
} // namespace tfprof
diff --git a/tensorflow/tools/tfprof/internal/advisor/checker.h b/tensorflow/tools/tfprof/internal/advisor/checker.h
index b8b057be5b..3ce80cd8c4 100644
--- a/tensorflow/tools/tfprof/internal/advisor/checker.h
+++ b/tensorflow/tools/tfprof/internal/advisor/checker.h
@@ -18,27 +18,33 @@ limitations under the License.
#include "tensorflow/core/lib/strings/str_util.h"
#include "tensorflow/tools/tfprof/internal/tfprof_stats.h"
+#include "tensorflow/tools/tfprof/tfprof_options.pb.h"
namespace tensorflow {
namespace tfprof {
-static const char* const kLevel[] = {
- "NOTE", // Good to know.
- "SUGGEST", // Might get better.
- "WARN", // Please do it for better.
+// Append only.
+static const char* const kCheckers[] = {
+ "AcceleratorUtilizationChecker", "OperationChecker",
+ "ExpensiveOperationChecker",
+ "JobChecker", // Internal checker.
};
class Checker {
public:
- virtual ~Checker(){};
+ virtual ~Checker() {}
- virtual string name() = 0;
+ virtual string name() const = 0;
- std::vector<string> Run(const TFStats* stats) { return Check(stats); }
+ AdviceProto::Checker Run(const AdvisorOptionsProto::CheckerOption& options,
+ const TFStats* stats) {
+ return Check(options, stats);
+ }
protected:
- // Returns a vector of string, each one being an advice.
- virtual std::vector<string> Check(const TFStats* stats) = 0;
+ virtual AdviceProto::Checker Check(
+ const AdvisorOptionsProto::CheckerOption& options,
+ const TFStats* stats) = 0;
};
} // namespace tfprof
} // namespace tensorflow
diff --git a/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h b/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h
index 1238b57f20..ed8ae571b6 100644
--- a/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h
+++ b/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h
@@ -17,13 +17,16 @@ limitations under the License.
#define THIRD_PARTY_TENSORFLOW_TOOLS_TFPROF_INTERNAL_ADVISOR_INTERNAL_CHECKER_RUNNER_H_
#include "tensorflow/tools/tfprof/internal/tfprof_utils.h"
+#include "tensorflow/tools/tfprof/tfprof_options.pb.h"
+#include "tensorflow/tools/tfprof/tfprof_output.pb.h"
namespace tensorflow {
namespace tfprof {
class TFStats;
-std::map<string, std::vector<string>> RunInternalCheckers(const TFStats* stats);
+AdviceProto RunInternalCheckers(const AdvisorOptionsProto& options,
+ const TFStats* stats);
} // namespace tfprof
} // namespace tensorflow
diff --git a/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner_dummy.cc b/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner_dummy.cc
index 8204d2b04e..67962c8e8b 100644
--- a/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner_dummy.cc
+++ b/tensorflow/tools/tfprof/internal/advisor/internal_checker_runner_dummy.cc
@@ -17,9 +17,9 @@ limitations under the License.
namespace tensorflow {
namespace tfprof {
-std::map<string, std::vector<string>> RunInternalCheckers(
- const TFStats* stats) {
- return std::map<string, std::vector<string>>();
+AdviceProto RunInternalCheckers(const AdvisorOptionsProto& options,
+ const TFStats* stats) {
+ return AdviceProto();
}
} // namespace tfprof
diff --git a/tensorflow/tools/tfprof/internal/advisor/operation_checker.h b/tensorflow/tools/tfprof/internal/advisor/operation_checker.h
index 2a05f9bfd0..4d0d68e3bf 100644
--- a/tensorflow/tools/tfprof/internal/advisor/operation_checker.h
+++ b/tensorflow/tools/tfprof/internal/advisor/operation_checker.h
@@ -24,10 +24,11 @@ namespace tfprof {
class OperationChecker : public Checker {
public:
- string name() override { return "OperationChecker"; }
+ string name() const override { return kCheckers[1]; }
private:
- std::vector<string> Check(const TFStats* stats) override {
+ AdviceProto::Checker Check(const AdvisorOptionsProto::CheckerOption& options,
+ const TFStats* stats) override {
if (!stats) {
fprintf(stderr, "Missing profiles (e.g. graph, run_meta). Skip %s\n",
name().c_str());
@@ -53,22 +54,20 @@ class OperationChecker : public Checker {
}
}
if (use_batch_norm && !use_fused_batch_norm) {
- reports_.push_back(strings::Printf(
- "%s: Maybe use faster FusedBatchNorm instead of BatchNorm",
- kLevel[1]));
+ reports_.add_reports(
+ "Maybe use faster FusedBatchNorm instead of BatchNorm");
}
if (recommend_nchw) {
// TODO(xpan): Maybe print which Op supports NCHW.
- reports_.push_back(strings::Printf(
- "%s: Found operation using NHWC data_format on GPU. Maybe "
- "NCHW is faster.",
- kLevel[1]));
+ reports_.add_reports(
+ "Found operation using NHWC data_format on GPU. Maybe "
+ "NCHW is faster.");
}
return reports_;
}
private:
- std::vector<string> reports_;
+ AdviceProto::Checker reports_;
};
} // namespace tfprof
diff --git a/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor.h b/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor.h
index 856f515459..d2257fb9b5 100644
--- a/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor.h
+++ b/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor.h
@@ -18,8 +18,10 @@ limitations under the License.
#include "tensorflow/tools/tfprof/internal/advisor/accelerator_utilization_checker.h"
#include "tensorflow/tools/tfprof/internal/advisor/checker.h"
+#include "tensorflow/tools/tfprof/internal/advisor/expensive_operation_checker.h"
#include "tensorflow/tools/tfprof/internal/advisor/internal_checker_runner.h"
#include "tensorflow/tools/tfprof/internal/advisor/operation_checker.h"
+#include "tensorflow/tools/tfprof/tfprof_options.pb.h"
namespace tensorflow {
namespace tfprof {
@@ -29,23 +31,44 @@ class Advisor {
public:
Advisor(const TFStats* stats) : stats_(stats) {}
- std::map<string, std::vector<string>> Advise() {
+ static AdvisorOptionsProto DefaultOptions() {
+ AdvisorOptionsProto options;
+ std::vector<string> checkers(
+ kCheckers, kCheckers + sizeof(kCheckers) / sizeof(*kCheckers));
+ for (const string& checker : checkers) {
+ (*options.mutable_checkers())[checker];
+ }
+ return options;
+ }
+
+ AdviceProto Advise(const AdvisorOptionsProto& options) {
// Note: Release a checker's memory ASAP.
- std::map<string, std::vector<string>> reports = RunInternalCheckers(stats_);
- // TODO(xpan): Think of a way to turn off/on specific checkers.
- AcceleratorUtilizationChecker au_checker;
- reports[au_checker.name()] = au_checker.Run(stats_);
- OperationChecker op_checker;
- reports[op_checker.name()] = op_checker.Run(stats_);
-
- for (const auto& checker_r : reports) {
- fprintf(stdout, "%s reports:\n", checker_r.first.c_str());
- for (const auto& r : checker_r.second) {
+ AdviceProto ret = RunInternalCheckers(options, stats_);
+
+ if (options.checkers().find(kCheckers[0]) != options.checkers().end()) {
+ AcceleratorUtilizationChecker au_checker;
+ (*ret.mutable_checkers())[kCheckers[0]].MergeFrom(
+ au_checker.Run(options.checkers().at(kCheckers[0]), stats_));
+ }
+ if (options.checkers().find(kCheckers[1]) != options.checkers().end()) {
+ OperationChecker op_checker;
+ (*ret.mutable_checkers())[kCheckers[1]].MergeFrom(
+ op_checker.Run(options.checkers().at(kCheckers[1]), stats_));
+ }
+ if (options.checkers().find(kCheckers[2]) != options.checkers().end()) {
+ ExpensiveOperationChecker expensive_op_checker;
+ (*ret.mutable_checkers())[kCheckers[2]].MergeFrom(
+ expensive_op_checker.Run(options.checkers().at(kCheckers[2]),
+ stats_));
+ }
+ for (const auto& checker : ret.checkers()) {
+ fprintf(stdout, "\n%s:\n", checker.first.c_str());
+ for (const string& r : checker.second.reports()) {
fprintf(stdout, "%s\n", r.c_str());
}
}
fflush(stdout);
- return reports;
+ return ret;
}
private:
diff --git a/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor_test.cc b/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor_test.cc
index b41d0770dc..3b40253954 100644
--- a/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor_test.cc
+++ b/tensorflow/tools/tfprof/internal/advisor/tfprof_advisor_test.cc
@@ -29,15 +29,16 @@ class TFProfAdvisorTest : public ::testing::Test {
nullptr, nullptr));
stats_->AddNodeForTest(
- "n1", CreateNode("n1", "Conv2D", {{"data_format", "NHWC"}}, 10, 2));
- stats_->AddNodeForTest("n2", CreateNode("n2", "Conv2D", {}, 20, 2));
+ 0, CreateNode("n1", "Conv2D", {{"data_format", "NHWC"}}, 0, 10, 2));
+ stats_->AddNodeForTest(0, CreateNode("n2", "Conv2D", {}, 0, 20, 2));
+ stats_->BuildAllViews();
advisor_.reset(new Advisor(stats_.get()));
}
std::unique_ptr<TFGraphNode> CreateNode(const string& name,
const string& type,
std::map<string, string> attrs,
- int64 start_miros,
+ int64 step, int64 start_miros,
int64 end_rel_micros) {
node_defs_.push_back(std::unique_ptr<NodeDef>(new NodeDef()));
NodeDef* def = node_defs_.back().get();
@@ -52,10 +53,10 @@ class TFProfAdvisorTest : public ::testing::Test {
NodeExecStats node_stat;
node_stat.set_all_start_micros(start_miros);
node_stat.set_op_end_rel_micros(end_rel_micros);
- node->AddStepStat(0, "/job:localhost/replica:0/task:0/gpu:0", node_stat);
- node->AddStepStat(0, "/job:localhost/replica:0/task:0/gpu:0:stream:all",
+ node->AddStepStat(step, "/job:localhost/replica:0/task:0/gpu:0", node_stat);
+ node->AddStepStat(step, "/job:localhost/replica:0/task:0/gpu:0:stream:all",
node_stat);
- node->AddStepStat(0, "/job:localhost/replica:0/task:0/gpu:0:stream:0",
+ node->AddStepStat(step, "/job:localhost/replica:0/task:0/gpu:0:stream:0",
node_stat);
return node;
}
@@ -66,23 +67,38 @@ class TFProfAdvisorTest : public ::testing::Test {
};
TEST_F(TFProfAdvisorTest, Basics) {
- std::map<string, std::vector<string>> reports = advisor_->Advise();
- EXPECT_TRUE(reports.find("AcceleratorUtilizationChecker") != reports.end());
- EXPECT_TRUE(reports.find("OperationChecker") != reports.end());
+ AdvisorOptionsProto options = Advisor::DefaultOptions();
+ AdviceProto advice = advisor_->Advise(options);
+ EXPECT_TRUE(advice.checkers().find(kCheckers[0]) != advice.checkers().end());
+ EXPECT_TRUE(advice.checkers().find(kCheckers[1]) != advice.checkers().end());
+ EXPECT_TRUE(advice.checkers().find(kCheckers[2]) != advice.checkers().end());
}
TEST_F(TFProfAdvisorTest, OperationChecker) {
- std::map<string, std::vector<string>> reports = advisor_->Advise();
- EXPECT_EQ(reports["OperationChecker"].size(), 1);
- EXPECT_TRUE(StringPiece(reports["OperationChecker"][0]).contains("NCHW"));
+ AdvisorOptionsProto options;
+ (*options.mutable_checkers())[kCheckers[1]];
+ AdviceProto advice = advisor_->Advise(options);
+ EXPECT_EQ(advice.checkers().at(kCheckers[1]).reports_size(), 1);
+ EXPECT_TRUE(StringPiece(advice.checkers().at(kCheckers[1]).reports(0))
+ .contains("NCHW"));
}
TEST_F(TFProfAdvisorTest, UtilizationChecker) {
- std::map<string, std::vector<string>> reports = advisor_->Advise();
- EXPECT_EQ(reports["AcceleratorUtilizationChecker"].size(), 1);
- EXPECT_TRUE(StringPiece(reports["AcceleratorUtilizationChecker"][0])
+ AdvisorOptionsProto options;
+ (*options.mutable_checkers())[kCheckers[0]];
+ AdviceProto advice = advisor_->Advise(options);
+ EXPECT_EQ(advice.checkers().at(kCheckers[0]).reports_size(), 1);
+ EXPECT_TRUE(StringPiece(advice.checkers().at(kCheckers[0]).reports(0))
.contains("low utilization"));
}
+TEST_F(TFProfAdvisorTest, ExpensiveOperationChecker) {
+ AdvisorOptionsProto options;
+ (*options.mutable_checkers())[kCheckers[2]];
+ AdviceProto advice = advisor_->Advise(options);
+ EXPECT_TRUE(StringPiece(advice.checkers().at(kCheckers[2]).reports(0))
+ .contains("top 1 operation type: Conv2D"));
+}
+
} // namespace tfprof
} // namespace tensorflow
diff --git a/tensorflow/tools/tfprof/internal/print_model_analysis.cc b/tensorflow/tools/tfprof/internal/print_model_analysis.cc
index 37d01db3a1..5a9c44d8e6 100644
--- a/tensorflow/tools/tfprof/internal/print_model_analysis.cc
+++ b/tensorflow/tools/tfprof/internal/print_model_analysis.cc
@@ -27,6 +27,7 @@ limitations under the License.
#include "tensorflow/tools/tfprof/internal/tfprof_options.h"
#include "tensorflow/tools/tfprof/internal/tfprof_stats.h"
#include "tensorflow/tools/tfprof/tfprof_log.pb.h"
+#include "tensorflow/tools/tfprof/tfprof_options.pb.h"
#include "tensorflow/tools/tfprof/tfprof_output.pb.h"
namespace tensorflow {
@@ -36,6 +37,18 @@ TFStats* tf_stat = nullptr;
string RunProfile(const string& command, const string& options,
TFStats* tf_stats) {
+ if (command == kCmds[4]) {
+ AdvisorOptionsProto option_pb;
+ if (!option_pb.ParseFromString(options)) {
+ fprintf(stderr, "Cannot parse AdvisorOptionsProto\n");
+ return "";
+ }
+ tf_stats->BuildAllViews();
+ return Advisor(tf_stats).Advise(option_pb).SerializeAsString();
+ } else {
+ tf_stats->BuildView(command);
+ }
+
Options opts;
tensorflow::Status s = Options::FromProtoStr(options, &opts);
if (!s.ok()) {
@@ -97,14 +110,14 @@ void AddStep(int64 step, const string* run_meta, const string* op_log) {
// TODO(xpan): Better error handling.
std::unique_ptr<RunMetadata> run_meta_ptr(new RunMetadata());
run_meta_ptr->ParseFromString(*run_meta);
- tf_stat->ParseRunMeta(step, std::move(run_meta_ptr));
+ tf_stat->AddRunMeta(step, std::move(run_meta_ptr));
std::unique_ptr<OpLog> op_log_ptr;
if (op_log && !op_log->empty()) {
op_log_ptr.reset(new OpLog());
op_log_ptr->ParseFromString(*op_log);
}
- tf_stat->ParseOpLog(std::move(op_log_ptr));
+ tf_stat->AddOpLog(std::move(op_log_ptr));
}
string Profile(const string* command, const string* options) {
@@ -144,7 +157,5 @@ string PrintModelAnalysis(const string* graph, const string* run_meta,
return RunProfile(*command, *options, &tf_stats);
}
-void Advise() { Advisor(tf_stat).Advise(); }
-
} // namespace tfprof
} // namespace tensorflow
diff --git a/tensorflow/tools/tfprof/internal/print_model_analysis.h b/tensorflow/tools/tfprof/internal/print_model_analysis.h
index 84165e542d..46db63646d 100644
--- a/tensorflow/tools/tfprof/internal/print_model_analysis.h
+++ b/tensorflow/tools/tfprof/internal/print_model_analysis.h
@@ -39,8 +39,6 @@ void AddStep(int64 step, const string* run_meta, const string* op_log);
string Profile(const string* command, const string* options);
-void Advise();
-
// Single-step Profiler.
//
// Interface defined for Python API swig. Calls the tfprof core API.
diff --git a/tensorflow/tools/tfprof/internal/tfprof_graph.h b/tensorflow/tools/tfprof/internal/tfprof_graph.h
index fbeae8673d..194a21f0cc 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_graph.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_graph.h
@@ -54,8 +54,8 @@ class TFGraph : public TFShow {
const ShowNode* ShowInternal(const Options& opts,
Timeline* timeline) override;
- bool ShouldShowIfExtra(ShowNode* node, const Options& opts,
- int depth) override {
+ bool ShouldShowIfExtra(const ShowNode* node, const Options& opts,
+ int depth) const override {
return true;
}
diff --git a/tensorflow/tools/tfprof/internal/tfprof_op.cc b/tensorflow/tools/tfprof/internal/tfprof_op.cc
index 6a7077c085..77a2593623 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_op.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_op.cc
@@ -126,6 +126,7 @@ const ShowMultiNode* TFOp::ShowInternal(const Options& opts,
}
nodes = SortNodes(nodes, opts);
+ // pre keeps track of previous visited node.
OpNode* pre = nullptr;
std::vector<OpNode*> account_nodes;
for (auto it = nodes.rbegin(); it != nodes.rend(); ++it) {
@@ -170,16 +171,20 @@ const ShowMultiNode* TFOp::ShowInternal(const Options& opts,
root_->ResetTotalStats();
if (pre) {
root_->AggregateTotalStats(pre);
- root_->mutable_proto()->add_children()->MergeFrom(pre->proto());
- pre->mutable_proto()->clear_children();
}
}
+ if (pre) {
+ root_->mutable_proto()->add_children()->MergeFrom(pre->proto());
+ pre->mutable_proto()->clear_children();
+ }
if (opts.output_type == kOutput[1] || opts.output_type == kOutput[2]) {
string display_str = FormatLegend(opts);
for (OpNode* node : show_nodes) {
display_str += FormatNode(node, root_.get(), opts);
}
+ // In op view, we don't show root (total). But it will still in proto.
+ // TODO(xpan): Is it the right choice?
root_->formatted_str = display_str;
}
return root_.get();
@@ -201,7 +206,7 @@ int64 TFOp::SearchRoot(const std::vector<OpNode*> nodes,
return i;
}
-string TFOp::FormatNode(OpNode* node, OpNode* root, const Options& opts) {
+string TFOp::FormatNode(OpNode* node, OpNode* root, const Options& opts) const {
std::vector<string> attrs;
if (opts.select.find(kShown[0]) != opts.select.end()) {
diff --git a/tensorflow/tools/tfprof/internal/tfprof_op.h b/tensorflow/tools/tfprof/internal/tfprof_op.h
index 5b16490363..34812f54be 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_op.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_op.h
@@ -56,15 +56,15 @@ class TFOp : public TFMultiShow {
int64 SearchRoot(const std::vector<OpNode*> nodes,
const std::vector<string>& regexes);
- bool ShouldShowIfExtra(ShowMultiNode* node, const Options& opts,
- int depth) override {
+ bool ShouldShowIfExtra(const ShowMultiNode* node, const Options& opts,
+ int depth) const override {
if (opts.min_occurrence > node->node->graph_nodes().size()) {
return false;
}
return true;
}
- string FormatNode(OpNode* node, OpNode* root, const Options& opts);
+ string FormatNode(OpNode* node, OpNode* root, const Options& opts) const;
std::unique_ptr<OpNode> root_;
std::map<string, std::unique_ptr<OpNode>> cnodes_map_;
diff --git a/tensorflow/tools/tfprof/internal/tfprof_options.h b/tensorflow/tools/tfprof/internal/tfprof_options.h
index 6c9db24342..d39333e3fc 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_options.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_options.h
@@ -59,10 +59,10 @@ static const char* const kShown[] = {
"cpu_micros"};
static const char* const kCmds[] = {
- "scope", "graph", "code", "op", "set", "help",
+ "scope", "graph", "code", "op", "advise", "set", "help",
};
-static const char* const kOutput[] = {"timeline", "stdout", "file"};
+static const char* const kOutput[] = {"timeline", "stdout", "file", "none"};
static const char* const kTimelineOpts[] = {
"outfile",
diff --git a/tensorflow/tools/tfprof/internal/tfprof_show.cc b/tensorflow/tools/tfprof/internal/tfprof_show.cc
index 40cc56fb22..6c1183a4d5 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_show.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_show.cc
@@ -26,7 +26,9 @@ namespace tensorflow {
namespace tfprof {
const TFGraphNodeProto& TFShow::Show(const Options& opts) {
- if (opts.output_type == kOutput[0]) {
+ if (opts.output_type == kOutput[3]) {
+ return ShowInternal(opts, nullptr)->proto();
+ } else if (opts.output_type == kOutput[0]) {
Timeline timeline(opts.step, opts.output_options.at(kTimelineOpts[0]));
return ShowInternal(opts, &timeline)->proto();
} else if (opts.output_type == kOutput[2]) {
@@ -64,7 +66,8 @@ bool TFShow::LookUpCheckPoint(const string& name,
return true;
}
-bool TFShow::ShouldShow(ShowNode* node, const Options& opts, int depth) {
+bool TFShow::ShouldShow(const ShowNode* node, const Options& opts,
+ int depth) const {
// Always show kTFProfRoot.
if (node->name() == kTFProfRoot) return true;
@@ -97,7 +100,8 @@ bool TFShow::ShouldShow(ShowNode* node, const Options& opts, int depth) {
return true;
}
-bool TFShow::ShouldTrim(ShowNode* node, const std::vector<string>& regexes) {
+bool TFShow::ShouldTrim(const ShowNode* node,
+ const std::vector<string>& regexes) const {
for (const string& regex : regexes) {
if (RE2::FullMatch(node->name(), regex)) {
return true;
@@ -122,7 +126,7 @@ bool TFShow::ReAccount(ShowNode* node, const Options& opts) {
return false;
}
-string TFShow::FormatNode(ShowNode* node, const Options& opts) {
+string TFShow::FormatNode(ShowNode* node, const Options& opts) const {
std::vector<string> info;
if (opts.select.find(kShown[2]) != opts.select.end()) {
const string shape = FormatShapes(node->node->shape());
@@ -210,7 +214,7 @@ string TFShow::FormatNode(ShowNode* node, const Options& opts) {
str_util::Join(info, ", ").c_str());
}
-string TFShow::FormatLegend(const Options& opts) {
+string TFShow::FormatLegend(const Options& opts) const {
std::vector<string> legends;
if (opts.select.find(kShown[2]) != opts.select.end()) {
legends.push_back("# parameters");
diff --git a/tensorflow/tools/tfprof/internal/tfprof_show.h b/tensorflow/tools/tfprof/internal/tfprof_show.h
index 2c61b4fd73..95513e086f 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_show.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_show.h
@@ -54,20 +54,21 @@ class TFShow {
std::unique_ptr<TFProfTensor>* tensor);
// Overridden by subclass if extra requirements need to be met.
- virtual bool ShouldShowIfExtra(ShowNode* node, const Options& opts,
- int depth) {
+ virtual bool ShouldShowIfExtra(const ShowNode* node, const Options& opts,
+ int depth) const {
return true;
}
- bool ShouldShow(ShowNode* node, const Options& opts, int depth);
+ bool ShouldShow(const ShowNode* node, const Options& opts, int depth) const;
- bool ShouldTrim(ShowNode* node, const std::vector<string>& regexes);
+ bool ShouldTrim(const ShowNode* node,
+ const std::vector<string>& regexes) const;
bool ReAccount(ShowNode* node, const Options& opts);
- string FormatNode(ShowNode* node, const Options& opts);
+ string FormatNode(ShowNode* node, const Options& opts) const;
- string FormatLegend(const Options& opts);
+ string FormatLegend(const Options& opts) const;
template <typename T>
std::vector<T*> SortNodes(const std::vector<T*>& nodes, const Options& opts) {
diff --git a/tensorflow/tools/tfprof/internal/tfprof_show_multi.cc b/tensorflow/tools/tfprof/internal/tfprof_show_multi.cc
index 7545b3d48b..84d542714a 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_show_multi.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_show_multi.cc
@@ -28,7 +28,9 @@ namespace tensorflow {
namespace tfprof {
const TFMultiGraphNodeProto& TFMultiShow::Show(const Options& opts) {
- if (opts.output_type == kOutput[0]) {
+ if (opts.output_type == kOutput[3]) {
+ return ShowInternal(opts, nullptr)->proto();
+ } else if (opts.output_type == kOutput[0]) {
Timeline timeline(opts.step, opts.output_options.at(kTimelineOpts[0]));
return ShowInternal(opts, &timeline)->proto();
} else if (opts.output_type == kOutput[2]) {
@@ -48,8 +50,8 @@ const TFMultiGraphNodeProto& TFMultiShow::Show(const Options& opts) {
}
}
-bool TFMultiShow::ShouldShow(ShowMultiNode* node, const Options& opts,
- int depth) {
+bool TFMultiShow::ShouldShow(const ShowMultiNode* node, const Options& opts,
+ int depth) const {
// Always show kTFProfRoot.
if (node->name() == kTFProfRoot) return true;
@@ -88,8 +90,8 @@ bool TFMultiShow::ShouldShow(ShowMultiNode* node, const Options& opts,
return true;
}
-bool TFMultiShow::ShouldTrim(ShowMultiNode* node,
- const std::vector<string>& regexes) {
+bool TFMultiShow::ShouldTrim(const ShowMultiNode* node,
+ const std::vector<string>& regexes) const {
for (const string& regex : regexes) {
if (RE2::FullMatch(node->name(), regex)) {
return true;
@@ -102,7 +104,7 @@ bool TFMultiShow::ReAccount(ShowMultiNode* node, const Options& opts) {
return node->ReInit(opts.step, opts.account_type_regexes);
}
-string TFMultiShow::FormatLegend(const Options& opts) {
+string TFMultiShow::FormatLegend(const Options& opts) const {
std::vector<string> legends;
if (opts.select.find(kShown[0]) != opts.select.end()) {
legends.push_back("output bytes");
@@ -142,7 +144,8 @@ string TFMultiShow::FormatLegend(const Options& opts) {
str_util::Join(legends, " | ").c_str());
}
-string TFMultiShow::FormatInputShapes(const TFMultiGraphNodeProto& proto) {
+string TFMultiShow::FormatInputShapes(
+ const TFMultiGraphNodeProto& proto) const {
// input_shape string -> (static defined count, run count, run_micros)
std::map<string, std::tuple<int64, int64, int64>> input_shapes_attr;
for (int i = 0; i < proto.graph_nodes_size(); ++i) {
@@ -199,7 +202,7 @@ string TFMultiShow::FormatInputShapes(const TFMultiGraphNodeProto& proto) {
}
std::vector<string> TFMultiShow::FormatTimes(const ShowMultiNode* node,
- const Options& opts) {
+ const Options& opts) const {
std::vector<string> attrs;
if (opts.select.find(kShown[1]) != opts.select.end()) {
attrs.push_back(FormatTotalExecTime(node, opts));
diff --git a/tensorflow/tools/tfprof/internal/tfprof_show_multi.h b/tensorflow/tools/tfprof/internal/tfprof_show_multi.h
index e6faf1231d..ce309816a9 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_show_multi.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_show_multi.h
@@ -55,21 +55,23 @@ class TFMultiShow {
std::unique_ptr<TFProfTensor>* tensor);
// Overridden by subclass if extra requirements need to be met.
- virtual bool ShouldShowIfExtra(ShowMultiNode* node, const Options& opts,
- int depth) {
+ virtual bool ShouldShowIfExtra(const ShowMultiNode* node, const Options& opts,
+ int depth) const {
return true;
}
- bool ShouldShow(ShowMultiNode* node, const Options& opts, int depth);
+ bool ShouldShow(const ShowMultiNode* node, const Options& opts,
+ int depth) const;
- bool ShouldTrim(ShowMultiNode* node, const std::vector<string>& regexes);
+ bool ShouldTrim(const ShowMultiNode* node,
+ const std::vector<string>& regexes) const;
bool ReAccount(ShowMultiNode* node, const Options& opts);
- string FormatLegend(const Options& opts);
- string FormatInputShapes(const TFMultiGraphNodeProto& proto);
+ string FormatLegend(const Options& opts) const;
+ string FormatInputShapes(const TFMultiGraphNodeProto& proto) const;
std::vector<string> FormatTimes(const ShowMultiNode* node,
- const Options& opts);
+ const Options& opts) const;
template <typename T>
std::vector<T*> SortNodes(const std::vector<T*>& nodes, const Options& opts) {
diff --git a/tensorflow/tools/tfprof/internal/tfprof_show_test.cc b/tensorflow/tools/tfprof/internal/tfprof_show_test.cc
index 18a7c51a20..46b6ebc09a 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_show_test.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_show_test.cc
@@ -65,6 +65,7 @@ class TFProfShowTest : public ::testing::Test {
tf_stats_.reset(new TFStats(std::move(graph_pb), std::move(run_meta_pb),
std::move(op_log_pb), std::move(ckpt_reader)));
+ tf_stats_->BuildAllViews();
}
std::unique_ptr<TFStats> tf_stats_;
diff --git a/tensorflow/tools/tfprof/internal/tfprof_stats.cc b/tensorflow/tools/tfprof/internal/tfprof_stats.cc
index f5b8dad4e2..64da7ae7cf 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_stats.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_stats.cc
@@ -29,16 +29,17 @@ TFStats::TFStats(std::unique_ptr<GraphDef> graph,
std::unique_ptr<RunMetadata> run_meta,
std::unique_ptr<OpLog> op_log,
std::unique_ptr<checkpoint::CheckpointReader> ckpt_reader)
- : graph_(std::move(graph)),
+ : has_code_traces_(false),
+ graph_(std::move(graph)),
ckpt_reader_(std::move(ckpt_reader)) {
CHECK(graph_) << "Must at least have GraphDef";
printf("Parsing Inputs...\n");
ParseGraph();
if (run_meta && run_meta->has_step_stats()) {
- ParseRunMeta(0, std::move(run_meta));
+ AddRunMeta(0, std::move(run_meta));
}
- ParseOpLog(std::move(op_log));
+ AddOpLog(std::move(op_log));
if (ckpt_reader_) {
for (const auto& v : ckpt_reader_->GetVariableToShapeMap()) {
@@ -48,27 +49,48 @@ TFStats::TFStats(std::unique_ptr<GraphDef> graph,
}
}
}
+}
- printf("Preparing Views...\n");
- scope_view_ = std::unique_ptr<TFScope>(new TFScope(ckpt_reader_.get()));
- graph_view_ = std::unique_ptr<TFGraph>(new TFGraph(ckpt_reader_.get()));
- code_view_ = std::unique_ptr<TFCode>(new TFCode());
- op_view_ = std::unique_ptr<TFOp>(new TFOp());
+void TFStats::BuildView(const string& cmd) {
+ if (cmd == kCmds[0] && !scope_view_) {
+ scope_view_.reset(new TFScope(ckpt_reader_.get()));
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ scope_view_->AddNode(it->second.get());
+ }
+ scope_view_->Build();
+ }
+ if (cmd == kCmds[1] && !graph_view_) {
+ graph_view_.reset(new TFGraph(ckpt_reader_.get()));
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ graph_view_->AddNode(it->second.get());
+ }
+ graph_view_->Build();
+ }
+ if (cmd == kCmds[2] && !code_view_) {
+ code_view_.reset(new TFCode());
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ code_view_->AddNode(it->second.get());
+ }
+ code_view_->Build();
+ }
+ if (cmd == kCmds[3] && !op_view_) {
+ op_view_.reset(new TFOp());
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ op_view_->AddNode(it->second.get());
+ }
+ op_view_->Build();
+ }
+}
- for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
- scope_view_->AddNode(it->second.get());
- graph_view_->AddNode(it->second.get());
- code_view_->AddNode(it->second.get());
- op_view_->AddNode(it->second.get());
- }
- scope_view_->Build();
- graph_view_->Build();
- code_view_->Build();
- op_view_->Build();
+void TFStats::BuildAllViews() {
+ std::vector<string> cmds_str(kCmds, kCmds + sizeof(kCmds) / sizeof(*kCmds));
+ for (const string& cmd : cmds_str) {
+ BuildView(cmd);
+ }
}
const TFGraphNodeProto& TFStats::ShowGraphNode(const string& cmd,
- const Options& opts) {
+ const Options& opts) const {
if (!Validate(opts)) {
return empty_graph_node_;
}
@@ -82,8 +104,8 @@ const TFGraphNodeProto& TFStats::ShowGraphNode(const string& cmd,
}
}
-const TFMultiGraphNodeProto& TFStats::ShowMultiGraphNode(const string& cmd,
- const Options& opts) {
+const TFMultiGraphNodeProto& TFStats::ShowMultiGraphNode(
+ const string& cmd, const Options& opts) const {
if (!Validate(opts)) {
return empty_multi_graph_node_;
}
@@ -130,7 +152,7 @@ void TFStats::ParseGraph() {
}
}
-void TFStats::ParseOpLog(std::unique_ptr<OpLog> op_log) {
+void TFStats::AddOpLog(std::unique_ptr<OpLog> op_log) {
if (!op_log) {
return;
}
@@ -144,12 +166,13 @@ void TFStats::ParseOpLog(std::unique_ptr<OpLog> op_log) {
node->second->AddFloatOps(entry.float_ops());
}
if (entry.has_code_def()) {
+ has_code_traces_ = true;
node->second->AddCode(entry.code_def());
}
}
}
-void TFStats::ParseRunMeta(int64 step, std::unique_ptr<RunMetadata> run_meta) {
+void TFStats::AddRunMeta(int64 step, std::unique_ptr<RunMetadata> run_meta) {
if (!run_meta || !run_meta->has_step_stats()) {
fprintf(stderr, "Invalid RunMetadata for step %lld\n", step);
return;
@@ -176,7 +199,7 @@ void TFStats::ParseRunMeta(int64 step, std::unique_ptr<RunMetadata> run_meta) {
}
}
-bool TFStats::Validate(const Options& opts) {
+bool TFStats::Validate(const Options& opts) const {
if (opts.step >= 0 && steps_.find(opts.step) == steps_.end()) {
fprintf(stderr, "Options -step=%lld not found\n", opts.step);
return false;
@@ -184,9 +207,9 @@ bool TFStats::Validate(const Options& opts) {
return true;
}
-void TFStats::AddNodeForTest(const string& name,
- std::unique_ptr<TFGraphNode> node) {
- nodes_map_[name] = std::move(node);
+void TFStats::AddNodeForTest(int64 step, std::unique_ptr<TFGraphNode> node) {
+ steps_.insert(step);
+ nodes_map_[node->name()] = std::move(node);
}
} // namespace tfprof
} // namespace tensorflow
diff --git a/tensorflow/tools/tfprof/internal/tfprof_stats.h b/tensorflow/tools/tfprof/internal/tfprof_stats.h
index dfb190e703..b26d274f80 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_stats.h
+++ b/tensorflow/tools/tfprof/internal/tfprof_stats.h
@@ -59,28 +59,38 @@ class TFStats {
const std::map<string, std::unique_ptr<TFGraphNode>>& nodes() const {
return nodes_map_;
}
+ const std::set<int64>& steps() const { return steps_; }
+ bool has_code_traces() const { return has_code_traces_; }
+ void BuildView(const string& cmd);
+ void BuildAllViews();
+
+ // Note: Must first BuildView(view_foo) before ShowXXX(view_foo) methods.
+ //
// Organize the TensorFlow model as different types of views, and generate
// outputs for profiling.
- const TFGraphNodeProto& ShowGraphNode(const string& cmd, const Options& opts);
+ // TODO(xpan): Should it return reference here?
+ const TFGraphNodeProto& ShowGraphNode(const string& cmd,
+ const Options& opts) const;
const TFMultiGraphNodeProto& ShowMultiGraphNode(const string& cmd,
- const Options& opts);
+ const Options& opts) const;
// Add a step of run time meta data.
- void ParseRunMeta(int64 step, std::unique_ptr<RunMetadata> run_meta);
+ void AddRunMeta(int64 step, std::unique_ptr<RunMetadata> run_meta);
// Add tfprof operation meta data, such as customized op type, float_ops,
// and code traces.
- void ParseOpLog(std::unique_ptr<OpLog> op_log);
+ void AddOpLog(std::unique_ptr<OpLog> op_log);
// For test purpose only.
- void AddNodeForTest(const string& name, std::unique_ptr<TFGraphNode> node);
+ void AddNodeForTest(int64 step, std::unique_ptr<TFGraphNode> node);
private:
- bool Validate(const Options& opts);
+ bool Validate(const Options& opts) const;
void ParseGraph();
std::set<int64> steps_;
+ bool has_code_traces_;
std::unique_ptr<GraphDef> graph_;
std::unique_ptr<TFScope> scope_view_;
std::unique_ptr<TFGraph> graph_view_;
diff --git a/tensorflow/tools/tfprof/internal/tfprof_stats_test.cc b/tensorflow/tools/tfprof/internal/tfprof_stats_test.cc
index bcd1147c69..00d5d8cdb3 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_stats_test.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_stats_test.cc
@@ -66,6 +66,7 @@ class TFProfStatsTest : public ::testing::Test {
tf_stats_.reset(new TFStats(std::move(graph_pb), std::move(run_meta_pb),
std::move(op_log_pb), std::move(ckpt_reader)));
+ tf_stats_->BuildAllViews();
}
std::unique_ptr<TFStats> tf_stats_;
diff --git a/tensorflow/tools/tfprof/internal/tfprof_tensor_test.cc b/tensorflow/tools/tfprof/internal/tfprof_tensor_test.cc
index d7cfe7dade..0482657ca5 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_tensor_test.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_tensor_test.cc
@@ -50,6 +50,7 @@ class TFProfTensorTest : public ::testing::Test {
tf_stats_.reset(new TFStats(std::move(graph_pb), std::move(run_meta_pb),
std::move(op_log_pb), std::move(ckpt_reader)));
+ tf_stats_->BuildAllViews();
}
std::unique_ptr<TFStats> tf_stats_;
diff --git a/tensorflow/tools/tfprof/internal/tfprof_timeline_test.cc b/tensorflow/tools/tfprof/internal/tfprof_timeline_test.cc
index 0e9bb9658c..cad31050a9 100644
--- a/tensorflow/tools/tfprof/internal/tfprof_timeline_test.cc
+++ b/tensorflow/tools/tfprof/internal/tfprof_timeline_test.cc
@@ -52,6 +52,7 @@ class TFProfTimelineTest : public ::testing::Test {
tf_stats_.reset(new TFStats(std::move(graph_pb), std::move(run_meta_pb),
nullptr, nullptr));
+ tf_stats_->BuildAllViews();
}
std::unique_ptr<TFStats> tf_stats_;