Home | History | Annotate | Download | only in internal
      1 /* Copyright 2016 The TensorFlow Authors All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include "tensorflow/core/profiler/internal/tfprof_scope.h"
     17 
     18 #include <stdio.h>
     19 #include <utility>
     20 
     21 #include "tensorflow/c/c_api.h"
     22 #include "tensorflow/core/framework/tensor.h"
     23 #include "tensorflow/core/lib/strings/stringprintf.h"
     24 #include "tensorflow/core/platform/regexp.h"
     25 #include "tensorflow/core/profiler/internal/tfprof_constants.h"
     26 #include "tensorflow/core/profiler/internal/tfprof_tensor.h"
     27 
     28 namespace tensorflow {
     29 namespace tfprof {
     30 ScopeNode* TFScope::CreateParentNode(const string& name) {
     31   if (nodes_map_.find(name) != nodes_map_.end()) {
     32     return nodes_map_[name].get();
     33   }
     34   node_defs_.push_back(std::unique_ptr<NodeDef>(new NodeDef()));
     35   node_defs_.back()->set_name(name);
     36   node_defs_.back()->set_op(kTFScopeParent);
     37   parent_nodes_[name] = std::unique_ptr<TFGraphNode>(
     38       new TFGraphNode(node_defs_.back().get(), -1, nullptr));
     39   nodes_map_[name] =
     40       std::unique_ptr<ScopeNode>(new ScopeNode(parent_nodes_[name].get()));
     41   return nodes_map_[name].get();
     42 }
     43 
     44 void TFScope::AddNode(TFGraphNode* node) {
     45   string name = node->name();
     46   if (nodes_map_.find(node->name()) == nodes_map_.end()) {
     47     nodes_map_[name] = std::unique_ptr<ScopeNode>(new ScopeNode(node));
     48   }
     49 
     50   auto last_slash = name.find_last_of("/");
     51   while (last_slash != name.npos) {
     52     name = name.substr(0, last_slash);
     53     if (nodes_map_.find(name) == nodes_map_.end()) {
     54       CHECK(CreateParentNode(name));
     55     }
     56     last_slash = name.find_last_of("/");
     57   }
     58 }
     59 
     60 void TFScope::Build() {
     61   if (root_) return;
     62 
     63   std::vector<ScopeNode*> roots;
     64   // Found roots, which are nodes without "/".
     65   for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
     66     ScopeNode* node = it->second.get();
     67     auto last_slash = node->name().find_last_of("/");
     68     if (last_slash == string::npos) {
     69       roots.push_back(node);
     70     } else {
     71       const string prefix = node->name().substr(0, last_slash);
     72       nodes_map_[prefix]->children.push_back(node);
     73     }
     74   }
     75 
     76   root_ = CreateParentNode(kTFProfRoot);
     77   root_->children.assign(roots.begin(), roots.end());
     78 }
     79 
     80 const ShowNode* TFScope::ShowInternal(const Options& opts, Timeline* timeline) {
     81   root_->ResetTotalStats();
     82   if (opts.output_type == kOutput[3]) {
     83     fprintf(stderr, "Only 'code' view supports pprof output now.\n");
     84     return root_;
     85   }
     86 
     87   std::vector<ScopeNode*> roots = Account(root_->children, opts);
     88   root_->show_children.clear();
     89   for (ScopeNode* n : roots) {
     90     root_->AggregateTotalStats(n);
     91   }
     92 
     93   if (opts.start_name_regexes.size() != 1 ||
     94       opts.start_name_regexes[0] != ".*") {
     95     roots = SearchRoot(roots, opts.start_name_regexes);
     96   }
     97 
     98   root_->show_children.assign(roots.begin(), roots.end());
     99   ScopeNode* root = PrintScope({root_}, opts, 1, 0)[0];
    100 
    101   root->formatted_str = FormatLegend(opts) + root->formatted_str;
    102   Format(root->show_children, &root->formatted_str, root->mutable_proto());
    103 
    104   if (timeline) {
    105     timeline->GenerateScopeTimeline(root);
    106   }
    107   return root;
    108 }
    109 
    110 void TFScope::Format(const std::vector<ScopeNode*> roots, string* display_str,
    111                      GraphNodeProto* proto) {
    112   for (ScopeNode* node : roots) {
    113     display_str->append(node->formatted_str);
    114     GraphNodeProto* child = proto->add_children();
    115     child->MergeFrom(node->proto());
    116     Format(node->show_children, display_str, child);
    117   }
    118 }
    119 
    120 std::vector<ScopeNode*> TFScope::SearchRoot(
    121     std::vector<ScopeNode*> roots, const std::vector<string>& regexes) {
    122   std::vector<ScopeNode*> res;
    123   if (roots.empty()) {
    124     return res;
    125   }
    126   for (ScopeNode* root : roots) {
    127     bool match_start_node = false;
    128     for (const string& regex : regexes) {
    129       if (RE2::FullMatch(root->name(), regex)) {
    130         res.push_back(root);
    131         match_start_node = true;
    132         break;
    133       }
    134     }
    135     if (match_start_node) {
    136       // Found a start node at this branch, no need to continue.
    137       continue;
    138     }
    139     std::vector<ScopeNode*> nroots = SearchRoot(root->show_children, regexes);
    140     res.insert(res.end(), nroots.begin(), nroots.end());
    141   }
    142   return res;
    143 }
    144 
    145 std::vector<ScopeNode*> TFScope::PrintScope(const std::vector<ScopeNode*> roots,
    146                                             const Options& opts, int depth,
    147                                             int last_ident) {
    148   std::vector<ScopeNode*> show_nodes;
    149 
    150   for (ScopeNode* node : roots) {
    151     int ident = last_ident;
    152     bool show = ShouldShow(node, opts, depth);
    153     if (show) ident += 2;
    154 
    155     std::vector<ScopeNode*> show_cnodes;
    156     if (!ShouldTrim(node, opts.trim_name_regexes) && depth <= opts.max_depth) {
    157       show_cnodes = PrintScope(node->show_children, opts, depth + 1, ident);
    158     }
    159     if (show) {
    160       node->show_children.clear();
    161       if (opts.account_displayed_op_only) {
    162         node->ResetTotalStats();
    163         node->AddSelfToTotalStats();
    164       }
    165 
    166       show_cnodes = SortNodes(show_cnodes, opts);
    167       for (ScopeNode* sc : show_cnodes) {
    168         node->show_children.push_back(sc);
    169         if (opts.account_displayed_op_only) {
    170           node->AggregateTotalStats(sc);
    171         }
    172       }
    173 
    174       node->formatted_str =
    175           strings::Printf("%s%s\n", string(last_ident, ' ').c_str(),
    176                           FormatNode(node, opts).c_str());
    177 
    178       if (opts.select.find(kShown[4]) != opts.select.end()) {
    179         std::unique_ptr<TFProfTensor> tfprof_tensor;
    180         if (LookUpCheckPoint(node->name(), &tfprof_tensor)) {
    181           string value_str;
    182           tfprof_tensor->Display(&value_str,
    183                                  node->mutable_proto()->mutable_tensor_value());
    184           node->formatted_str += value_str;
    185         }
    186       }
    187       show_nodes.push_back(node);
    188     } else {
    189       show_nodes.insert(show_nodes.end(), show_cnodes.begin(),
    190                         show_cnodes.end());
    191     }
    192   }
    193   return show_nodes;
    194 }
    195 
    196 std::vector<ScopeNode*> TFScope::Account(const std::vector<ScopeNode*>& roots,
    197                                          const Options& opts) {
    198   std::vector<ScopeNode*> act_nodes;
    199 
    200   for (ScopeNode* node : roots) {
    201     node->ResetTotalStats();
    202     std::vector<ScopeNode*> act_cnodes = Account(node->children, opts);
    203 
    204     node->account = ReAccount(node, opts);
    205     if (node->account || !act_cnodes.empty()) {
    206       node->show_children.clear();
    207       node->ResetTotalStats();
    208       node->AddSelfToTotalStats();
    209       for (ScopeNode* c : act_cnodes) {
    210         node->AggregateTotalStats(c);
    211         node->show_children.push_back(c);
    212       }
    213       act_nodes.push_back(node);
    214     }
    215   }
    216   return act_nodes;
    217 }
    218 }  // namespace tfprof
    219 }  // namespace tensorflow
    220