diff --git a/linenoise.BUILD b/linenoise.BUILD
new file mode 100644
index 00000000000..9924a620f24
--- /dev/null
+++ b/linenoise.BUILD
@@ -0,0 +1,13 @@
+licenses(["notice"]) # 2-clause BSD
+
+exports_files(["LICENSE"])
+
+package(
+ default_visibility = ["//visibility:public"],
+)
+
+cc_library(
+ name = "linenoise",
+ srcs = ["linenoise.c"],
+ hdrs = ["linenoise.h"],
+)
diff --git a/tensorflow/BUILD b/tensorflow/BUILD
index 284be34a784..b70337bb917 100644
--- a/tensorflow/BUILD
+++ b/tensorflow/BUILD
@@ -124,6 +124,9 @@ filegroup(
"//tensorflow/contrib/tensor_forest/hybrid:all_files",
"//tensorflow/contrib/tensorboard:all_files",
"//tensorflow/contrib/testing:all_files",
+ "//tensorflow/contrib/tfprof/python/tools/tfprof:all_files",
+ "//tensorflow/contrib/tfprof/tools/tfprof:all_files",
+ "//tensorflow/contrib/tfprof/tools/tfprof/internal:all_files",
"//tensorflow/contrib/training:all_files",
"//tensorflow/contrib/util:all_files",
"//tensorflow/core:all_files",
diff --git a/tensorflow/contrib/tfprof/README.md b/tensorflow/contrib/tfprof/README.md
new file mode 100644
index 00000000000..0e6420134a5
--- /dev/null
+++ b/tensorflow/contrib/tfprof/README.md
@@ -0,0 +1,453 @@
+# tfprof: A Profiling Tool for TensorFlow Models
+
+go/tfprof
+
+Author: Xin Pan (xpan@google.com, github: panyx0718)
+
+Consultants: Jon Shlens (shlens@google.com), Pete Warden (petewarden@google.com)
+
+[TOC]
+
+## Introduction
+
+tfprof is a profiling tool for TensorFlow that analyzes model architectures
+and measures system performance.
+
+###Major Features
+
+1. Measure model parameters, float operations, tensor shapes.
+2. Measure op execution times, requested memory size and device placement.
+3. Inspect checkpoint tensors' shapes and their values.
+4. Explore model based on name scope or graph structure.
+5. Selectively grouping/filtering/accounting/ordering ops.
+
+### Interfaces
+
+[CLI Tutorials](#cli-tutorials):
+It supports interactive mode for exploration and single-shot mode for
+scripts. Outputs can be dumped to files or printed in terminal.
+
+Python API Tutorials: Python API is not released yet.
+
+## CLI Tutorials
+
+Tutorials are based on a 32 layers ResNet.
+TODO(xpan): Provide graph.pbtxt, model.ckpt, tfprof_log and run_meta download.
+
+### Examples
+
+1) Start `tfprof` command line tool
+
+```shell
+# Build the tool.
+bazel build -c opt tensorflow/contrib/tfprof/...
+
+# Help information, including detail 'option' instructions.
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof help
+#
+# The following commands will start tfprof interactive mode.
+#
+# Profile model shapes and parameters only.
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof \
+ --graph_path=/graph.pbtxt
+#
+# Additionally profile checkpoint statistics and values.
+# Use '-account_type_regexes _checkpoint_variables' to select
+# checkpoint tensors.
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof \
+ --graph_path=graph.pbtxt \
+ --checkpoint_path=model.ckpt
+#
+# Additionally profile ops requested memory and timing.
+# See CLI Input Files section on generating run_meta file.
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof \
+ --graph_path=graph.pbtxt \
+ --run_meta_path=run_meta \
+ --checkpoint_path=model.ckpt
+#
+# tfprof_log is used to define customized op types and float ops.
+# Use tfprof_logger.write_op_log() to create tfprof_log.
+# See 11) in Examples section on generating tfprof_log file.
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof \
+ --graph_path=graph.pbtxt \
+ --run_meta_path=run_meta \
+ --op_log_path=tfprof_log \
+ --checkpoint_path=model.ckpt
+```
+Note that `graph.pbtxt` is an ASCII text format.
+
+2) Press enter to show the default options
+
+```shell
+tfprof>
+tfprof>
+-max_depth 4
+-min_bytes 0
+-min_micros 0
+-min_params 0
+-min_float_ops 0
+-device_regexes .*
+-order_by name
+-account_type_regexes Variable
+-start_name_regexes .*
+-trim_name_regexes
+-show_name_regexes .*
+-hide_name_regexes IsVariableInitialized_[0-9]+,save\/.*,^zeros[0-9_]*
+-account_displayed_op_only false
+# supported select fileds. Availability depends on --[run_meta|checkpoint|op_log]_path.
+# [bytes|micros|params|float_ops|num_hidden_ops|tensor_value|device|op_types]
+-select params
+-viz false
+-dump_to_file
+```
+
+3) I want to see the `BatchNorm`'s gamma value in checkpoint.
+
+```shell
+# Requires --graph_path, --checkpoint_path.
+tfprof> scope -show_name_regexes unit_1_0.*gamma -select tensor_value -max_depth 5
+_TFProfRoot ()
+ unit_1_0/shared_activation/init_bn/gamma ()
+[1.80 2.10 2.06 1.91 2.26 1.86 1.81 1.37 1.78 1.85 1.96 1.54 2.04 2.34 2.22 1.99 ],
+ unit_1_0/sub2/bn2/gamma ()
+[1.57 1.83 1.30 1.25 1.59 1.14 1.26 0.82 1.19 1.10 1.48 1.01 0.82 1.23 1.21 1.14 ],
+```
+
+4) I want to see my checkpoint tensors shape and number of parameters.
+
+```shell
+# Requires --graph_path, --checkpoint_path.
+# Increase -max_depth to see all tensors.
+tfprof> scope -account_type_regexes _checkpoint_variables -select params -max_depth 4
+_TFProfRoot (--/930.58k params)
+ global_step (0/0 params)
+ init/init_conv/DW (3x3x3x16, 432/864 params)
+ pool_logit/DW (64x10, 640/1.28k params)
+ pool_logit/DW/Momentum (64x10, 640/640 params)
+ pool_logit/biases (10, 10/20 params)
+ pool_logit/biases/Momentum (10, 10/10 params)
+ unit_last/final_bn/beta (64, 64/128 params)
+ unit_last/final_bn/gamma (64, 64/128 params)
+ unit_last/final_bn/moving_mean (64, 64/64 params)
+ unit_last/final_bn/moving_variance (64, 64/64 params)
+```
+
+5) I defined an op named ‘cost’ to calculate the loss. I want to know what ops
+it depends on take a long time to run. Hint: Use the ‘graph’ command to explore
+graph dependencies.
+
+```shell
+# Requires --graph_path, --run_meta_path.
+tfprof> graph -start_name_regexes cost.* -max_depth 100 -min_micros 10000 -select micros -account_type_regexes .*
+_TFProfRoot (0us/3.61sec)
+ init/init_conv/Conv2D (11.75ms/3.10sec)
+ random_shuffle_queue_DequeueMany (3.09sec/3.09sec)
+ unit_1_0/sub2/conv2/Conv2D (74.14ms/3.19sec)
+ unit_1_3/sub2/conv2/Conv2D (60.75ms/3.34sec)
+ unit_2_4/sub2/conv2/Conv2D (73.58ms/3.54sec)
+ unit_3_3/sub2/conv2/Conv2D (10.26ms/3.60sec)
+```
+
+6) I want to know the expensive operations during the back propagation.
+Hint: tensorflow prepend ‘gradient’ to your defined name scopes. Use the ‘scope’
+command to explore based on name scope hierarchies.
+
+```shell
+# Requires --graph_path, --run_meta_path.
+tfprof> scope -start_name_regexes gradient.* -max_depth 100 -min_micros 20000 -select micros -account_type_regexes .*
+_TFProfRoot (0us/2.29sec)
+ gradients/unit_1_0/sub1/conv1/Conv2D_grad/Conv2DBackpropFilter (54.96ms/54.96ms)
+ gradients/unit_1_0/sub2/conv2/Conv2D_grad/Conv2DBackpropFilter (83.63ms/83.63ms)
+ gradients/unit_1_1/sub1/conv1/Conv2D_grad/Conv2DBackpropFilter (99.25ms/99.25ms)
+ gradients/unit_1_2/sub1/conv1/Conv2D_grad/Conv2DBackpropFilter (95.40ms/95.40ms)
+ gradients/unit_1_2/sub2/conv2/Conv2D_grad/Conv2DBackpropFilter (99.83ms/99.83ms)
+ gradients/unit_1_3/sub1/conv1/Conv2D_grad/Conv2DBackpropFilter (95.39ms/95.39ms)
+ ...
+```
+
+7) Show the number of float operations in the model.
+Note: float operations calculation depends on
+1) op.RegisterStatistics. If an op doesn’t
+have RegisterStatistics defined, its float operations cannot be counted.
+2) fully defined shape is also necessary in order to calculate flops.
+float operations number is provided by tensorflow::tfprof::OpLog logged from
+Python API.
+
+```shell
+# Requires --graph_path, --op_log_path.
+tfprof> scope -min_float_ops 1 -max_depth 10 -select float_ops -account_type_regexes .*
+_TFProfRoot (0/17.63b flops)
+ gradients/pool_logit/xw_plus_b/MatMul_grad/MatMul (163.84k/163.84k flops)
+ gradients/pool_logit/xw_plus_b/MatMul_grad/MatMul_1 (163.84k/163.84k flops)
+ init/init_conv/Conv2D (113.25m/113.25m flops)
+ pool_logit/xw_plus_b (1.28k/165.12k flops)
+ pool_logit/xw_plus_b/MatMul (163.84k/163.84k flops)
+ unit_1_0/sub1/conv1/Conv2D (603.98m/603.98m flops)
+ unit_1_0/sub2/conv2/Conv2D (603.98m/603.98m flops)
+ unit_1_1/sub1/conv1/Conv2D (603.98m/603.98m flops)
+ unit_1_1/sub2/conv2/Conv2D (603.98m/603.98m flops)
+ ...
+```
+
+8) Show the number of parameters of all `tf.trainable_variables()` in the model.
+
+```shell
+# Requires --graph_path --op_log_path.
+# store option for future commands.
+tfprof> set -account_type_regexes _trainable_variables
+tfprof> scope -max_depth 4 -select params
+_TFProfRoot (--/464.15k params)
+ init/init_conv/DW (3x3x3x16, 432/432 params)
+ pool_logit/DW (64x10, 640/640 params)
+ pool_logit/biases (10, 10/10 params)
+ unit_last/final_bn/beta (64, 64/64 params)
+ unit_last/final_bn/gamma (64, 64/64 params)
+```
+
+Where does “_trainable_variables” come from? It is from the OpLog file
+generated by write_op_log() Python API. write_op_log() help users create some
+common op types implicitly. Users can define their own op types and log it
+through the write_op_log() API.
+
+9) What if I’m lazy and don’t want to define op type? I have given my ops
+well-defined names in my model’s code. And want to use names to select a group
+of ops. Let’s try it!
+
+```shell
+tfprof> set -account_type_regexes .*
+tfprof> scope -show_name_regexes unit_2_1.*DW -max_depth 100 -account_displayed_op_only
+_TFProfRoot (0/18.43k params)
+ unit_2_1/sub1/conv1/DW (3x3x32x32, 9.22k/9.22k params)
+ unit_2_1/sub2/conv2/DW (3x3x32x32, 9.22k/9.22k params)
+```
+
+The above command allows you to filter ops that match specific names.
+`-account_displayed_op_only` asks tfprof to only account ops displayed
+in terminal. Otherwise, tfprof accounts all ops matched by
+`-account_type_regexes` recursively even if they are hidden due to some
+options such as -max_depth.
+
+10) TensorFlow has built-in op types. For example, built-in op type `Variable`
+seems to include `Variable's` created by your model. However, be careful when
+depending on it because TensorFlow creates extra `Variable` ops implicitly and
+the implicitly created ops can have the same prefix as the `Variable's` you
+defined.
+
+In the following example, extra `Variables` are created and “/Momentum” is
+appended to their names. This might cause you “model capacity” calculation
+to get wrong.
+
+```shell
+tfprof> scope -account_type_regexes Variable -max_depth 4 -select params
+_TFProfRoot (--/930.58k params)
+ global_step (1/1 params)
+ init/init_conv/DW (3x3x3x16, 432/864 params)
+ pool_logit/DW (64x10, 640/1.28k params)
+ pool_logit/DW/Momentum (64x10, 640/640 params)
+ pool_logit/biases (10, 10/20 params)
+ pool_logit/biases/Momentum (10, 10/10 params)
+ unit_last/final_bn/beta (64, 64/128 params)
+ unit_last/final_bn/gamma (64, 64/128 params)
+ unit_last/final_bn/moving_mean (64, 64/64 params)
+ unit_last/final_bn/moving_variance (64, 64/64 params)
+```
+
+
+11) A example of defining extra op type for ops using `OpLog`
+
+First, in Python code, create an `OpLog` proto and add op type
+information to it:
+
+```python
+op_log = tfprof_log_pb2.OpLog()
+entry = op_log.log_entries.add()
+entry.name = 'pool_logit/DW'
+entry.types.append('pool_logit')
+entry = op_log.log_entries.add()
+entry.name = 'pool_logit/biases'
+# Alternatively:
+# var = tf.get_variable(xxx)
+# entry.name = var.op.name
+entry.types.append('pool_logit')
+```
+
+Second, call write_op_log to write the OpLog proto.
+
+```python
+tfprof_logger.write_op_log(sess.graph, /tmp/my_op_log_dir, op_log)
+```
+
+Third, when starting the tfprof tool, specify
+"--op_log_path /tmp/my_op_log_dir/op_log"
+
+```shell
+tfprof> scope -account_type_regexes pool_logit -max_depth 4 -select params
+_TFProfRoot (--/650 params)
+ pool_logit/DW (64x10, 640/640 params)
+ pool_logit/biases (10, 10/10 params)
+```
+
+Note that when you call
+`tfprof_logger.write_op_log(...)`, the tool adds all `Variables` inside
+`tf.trainable_variables()` to `_trainable_variables`.
+
+12) Run tfprof in one-shot mode and dump result to file.
+
+```shell
+# Printed to stdout if --dump_to_file is not set.
+tfprof scope --graph_path /cns/ij-d/home/xpan/tfprof/graph.pbtxt \
+ --max_depth 3 \
+ --dump_to_file "/tmp/dump"
+Reading Files...
+Parsing GraphDef...
+Preparing Views...
+
+cat /tmp/dump
+_TFProfRoot (--/930.58k params)
+ global_step (0/0 params)
+ pool_logit/DW (64x10, 640/1.28k params)
+ pool_logit/biases (10, 10/20 params)
+```
+
+13) Analyze how balanced Variable are on parameter servers.
+
+In this tutorial, I'm going to use a seq2seq model, which are split
+on several gpus at workers and several parameter servers.
+
+In tfprof, 'device' is an op_type. For example, if op1 and op2 are placed on
+gpu0. They share an op_type called 'gpu0'.
+
+```shell
+bazel-bin/tensorflow/contrib/tfprof/tools/tfprof/tfprof \
+ --graph_path ~/tfprof/textsum/graph.pbtxt \
+ --run_meta_path ~/tfprof/textsum/run_meta
+
+# Looks like ps task 1 is holding twice more parameters than task 0.
+tfprof> scope -select device,params -account_type_regexes .*ps.*task:0.* -max_depth 1
+_TFProfRoot (--/25.81m params)
+tfprof> scope -select device,params -account_type_regexes .*ps.*task:1.* -max_depth 1
+_TFProfRoot (--/58.84m params)
+```
+
+### CLI Input Files
+
+tfprof command line inference (CLI) loads dumped files from a tensorflow model.
+Convert them into in-memory data structures. To use it, users need to specify
+the locations of the dumped files. The following are the dumped files loaded
+by tfprof:
+
+--graph_path: GraphDef text file (required). Used to build in-memory
+representation of the model. For example, graph.pbtxt written by tf.Supervisor
+is a candidate. If you are not using tf.Supervisor, you can easily get GraphDef
+using tf.Graph.as_graph_def() or other API.
+
+--run_meta_path: tensorflow::RunMetadata.
+Used to get the memory and time consumption of
+each op of the model. Users need to enable it. For example, the following code
+snippet writes a RunMetadata file:
+
+```python
+run_options = config_pb2.RunOptions(trace_level=config_pb2.RunOptions.FULL_TRACE)
+run_metadata = config_pb2.RunMetadata()
+# Once a while, call it the get the RunMeta.
+_ = self._sess.run(..., options=run_options, run_metadata=run_metadata)
+with gfile.Open(os.path.join(output_dir, "run_meta"), "w") as f:
+ f.write(run_metadata.SerializeToString())
+```
+
+--op_log_path:
+tensorflow::tfprof::OpLog. A proto used to provide extra op information
+for ops. By giving a group of ops a type name, users can easily aggregate the
+statistics for those ops without accidently missing or including extra ops.
+tfprof exposes the following Python API to add op information and logging.
+
+```python
+ def write_op_log(graph, log_dir, op_log=None)
+```
+
+--checkpoint_path:
+TensorFlow checkpoint. It defines _checkpoint_variable op type. It also
+provides checkpointed tensors' values.
+
+
+## Design
+
+
+### In-memory representation
+
+Scope: This representation organizes ops based on name scope hierarchy,
+similar to filesystem hierarchy. Hence, it is essentially a tree data structure.
+For example op1 with name “name1/name2” is a child of op2 with name “name1”.
+
+Graph: The representation organizes ops based on op inputs. Hence it is
+a graph structure. The graph is a “directed acyclic graph” (hopefully), with
+direction from “output to input”. The direction is design this way so that users
+can trace from “result” to its “sources”.
+
+### Command line options
+
+tfprof’s major goals are to measure system performance and quicly analyze
+model architectures. Hence, its commands and options should allow users to achieve
+these 2 goals easily.
+
+graph: It is expected that users will mostly use graph representation to
+debug system performance. Hence, tfprof supports graph command, which pulls the
+graph in-memory representation described above.
+
+scope: It is expected that some users might want to explore their model
+statistics using the name scope information they defined in the Python codes.
+Hence, tfprof supports “scope” command, which pulls the tree in-memory
+representation.
+
+set: It is used to store the options so that user doesn’t need to
+re-type the same option again and again in the follow up command line. Note that
+tfprof has traditional terminal’s history and auto-complete support.
+
+help: print help information.
+
+Options: Run “tfprof help” to get detailed explanations.
+
+```python
+"-max_depth",
+"-min_bytes",
+"-min_micros",
+"-min_params",
+"-min_float_ops",
+"-order_by",
+"-account_type_regexes",
+"-start_name_regexes",
+"-trim_name_regexes",
+"-show_name_regexes",
+"-hide_name_regexes",
+"-account_displayed_op_only",
+"-select",
+"-viz", # Only supported for graph command.
+"-dump_to_file",
+```
+
+A key design is that stats are aggregated from descendants up to ancestors.
+`-account_type_regexes` is used to decide which ops stat is accounted. It makes
+decision based on op type. Usually set it to `.*` if no extra type information
+is added to the ops using OpLog. Intuitively, only accounted ops are displayed.
+`-min/max` and `-show/hide/trim/start` options are only used the optionally
+displayed or hide ops based on ops’ name and stats. However, they don’t prevent
+tfprof from accounting stats of hidden ops. Hence, the stat of a op can be
+aggregated by its parent even if it is hidden. `-account_displayed_op_only` is
+an option to break this rule. When it is set, only displayed ops are accounted.
+
+Regexes are all comma-separated, for example `-show_name_regexes`
+`regex1.*,regex2.*`. It is designed this way because it is convenient and comma
+is not expected to show up in op names.
+
+`-order_by` is used to order displayed ops. Displayed ops at the same hierarchy
+(notice the indent printed) are sorted according to order_by.
+
+## Future Work
+
+* Load SummaryWriter event logs so that it can show the latest summary value.
+
+* Better sorting and aggregation of outputs. Easier comprehension.
+
+* Currently, shape information is based on `graph.pbtxt`. When the shape
+information is incomplete, tfprof ignores it. See if it can use `RunMetadata`
+and `Checkpoint` to complete shape information.
diff --git a/tensorflow/contrib/tfprof/python/tools/tfprof/BUILD b/tensorflow/contrib/tfprof/python/tools/tfprof/BUILD
new file mode 100644
index 00000000000..d78020bbd87
--- /dev/null
+++ b/tensorflow/contrib/tfprof/python/tools/tfprof/BUILD
@@ -0,0 +1,31 @@
+package(
+ default_visibility = ["//visibility:public"],
+)
+
+licenses(["notice"]) # Apache 2.0
+
+py_library(
+ name = "tfprof_logger",
+ srcs = ["tfprof_logger.py"],
+ srcs_version = "PY2AND3",
+ deps = [
+ "//tensorflow:tensorflow_py",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_py",
+ "//tensorflow/python:framework_for_generated_wrappers",
+ ],
+)
+
+# -----------------------------------------------------------------------------
+# Google-internal targets. These must be at the end for syncrepo.
+
+filegroup(
+ name = "all_files",
+ srcs = glob(
+ ["**/*"],
+ exclude = [
+ "**/METADATA",
+ "**/OWNERS",
+ ],
+ ),
+ visibility = ["//tensorflow:__subpackages__"],
+)
diff --git a/tensorflow/contrib/tfprof/python/tools/tfprof/__init__.py b/tensorflow/contrib/tfprof/python/tools/tfprof/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/tensorflow/contrib/tfprof/python/tools/tfprof/tfprof_logger.py b/tensorflow/contrib/tfprof/python/tools/tfprof/tfprof_logger.py
new file mode 100644
index 00000000000..4a487461a38
--- /dev/null
+++ b/tensorflow/contrib/tfprof/python/tools/tfprof/tfprof_logger.py
@@ -0,0 +1,114 @@
+# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ==============================================================================
+"""Logging tensorflow::tfprof::OpLog.
+
+OpLog is used to add extra model information for offline analysis by tfprof.
+"""
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import os
+
+import tensorflow as tf
+from tensorflow.contrib.tfprof.python.tools.tfprof import tfprof_log_pb2
+from tensorflow.python.framework import ops
+
+TRAINABLE_VARIABLES = '_trainable_variables'
+REGISTERED_FLOP_STATS = 'flops'
+
+
+def _get_logged_ops(graph):
+ """Extract trainable model parameters and FLOPs for ops from a Graph.
+
+ Args:
+ graph: tf.Graph.
+ Returns:
+ logged_ops: dict mapping from op_name to OpLogEntry.
+ """
+ logged_ops = {}
+
+ graph_def = graph.as_graph_def()
+ for node in graph_def.node:
+ try:
+ stats = ops.get_stats_for_node_def(graph, node, REGISTERED_FLOP_STATS)
+ except ValueError:
+ # Catch Exception When shape is incomplete. Skip it.
+ stats = None
+
+ if not stats or not stats.value:
+ continue
+ if node.name not in logged_ops:
+ entry = tfprof_log_pb2.OpLogEntry()
+ entry.name = node.name
+ entry.float_ops = stats.value
+ logged_ops[entry.name] = entry
+
+ for v in graph.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES):
+ if v.op.name not in logged_ops:
+ entry = tfprof_log_pb2.OpLogEntry()
+ entry.name = v.op.name
+ entry.types.append(TRAINABLE_VARIABLES)
+ logged_ops[entry.name] = entry
+ else:
+ logged_ops[v.op.name].types.append(TRAINABLE_VARIABLES)
+ return logged_ops
+
+
+def _merge_default_with_oplog(graph, op_log=None):
+ """Merge the tfprof default extra info with caller's op_log.
+
+ Args:
+ graph: tf.Graph.
+ op_log: OpLog proto.
+ Returns:
+ tmp_op_log: Merged OpLog proto.
+ """
+ tmp_op_log = tfprof_log_pb2.OpLog()
+ logged_ops = _get_logged_ops(graph)
+ if not op_log:
+ tmp_op_log.log_entries.extend(logged_ops.values())
+ else:
+ all_ops = dict()
+ for entry in op_log.log_entries:
+ all_ops[entry.name] = entry
+ for op_name, entry in logged_ops.iteritems():
+ if op_name in all_ops:
+ all_ops[op_name].types.extend(entry.types)
+ if entry.float_ops > 0 and all_ops[op_name].float_ops == 0:
+ all_ops[op_name].float_ops = entry.float_ops
+ else:
+ all_ops[op_name] = entry
+ tmp_op_log.log_entries.extend(all_ops.values())
+ return tmp_op_log
+
+
+def write_op_log(graph, log_dir, op_log=None):
+ """Log provided 'op_log', and add additional model information below.
+
+ The API also assigns ops in tf.trainable_variables() an op type called
+ '_trainable_variables'.
+ The API also logs 'flops' statistics for ops with op.RegisterStatistics()
+ defined.
+
+ Args:
+ graph: tf.Graph.
+ log_dir: directory to write the log file.
+ op_log: OpLog proto.
+ """
+ op_log = _merge_default_with_oplog(graph, op_log)
+
+ with tf.gfile.Open(os.path.join(log_dir, 'tfprof_log'), 'w') as log:
+ log.write(op_log.SerializeToString())
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/BUILD b/tensorflow/contrib/tfprof/tools/tfprof/BUILD
new file mode 100644
index 00000000000..da161b1ffa1
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/BUILD
@@ -0,0 +1,52 @@
+package(
+ default_visibility = ["//visibility:public"],
+)
+
+licenses(["notice"]) # Apache 2.0
+
+# -----------------------------------------------------------------------------
+# Google-internal targets. These must be at the end for syncrepo.
+
+filegroup(
+ name = "all_files",
+ srcs = glob(
+ ["**/*"],
+ exclude = [
+ "**/METADATA",
+ "**/OWNERS",
+ ],
+ ),
+ visibility = ["//tensorflow:__subpackages__"],
+)
+
+cc_binary(
+ name = "tfprof",
+ srcs = ["tfprof_main.cc"],
+ deps = [
+ ":protos_all_cc",
+ "//tensorflow/c:c_api",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof/internal:tfprof_options",
+ "//tensorflow/contrib/tfprof/tools/tfprof/internal:tfprof_stats",
+ "//tensorflow/contrib/tfprof/tools/tfprof/internal:tfprof_utils",
+ "//tensorflow/core:framework_headers_lib",
+ "//tensorflow/core:framework_internal",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ "@linenoise//:linenoise",
+ ],
+)
+
+load("//tensorflow/core:platform/default/build_config.bzl", "tf_proto_library")
+
+tf_proto_library(
+ name = "protos_all",
+ srcs = glob(
+ ["**/*.proto"],
+ ),
+ cc_api_version = 2,
+ cc_libs = ["//tensorflow/core:protos_all_cc"],
+ go_api_version = 2,
+ java_api_version = 2,
+ visibility = ["//visibility:public"],
+)
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/BUILD b/tensorflow/contrib/tfprof/tools/tfprof/internal/BUILD
new file mode 100644
index 00000000000..42812b345dc
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/BUILD
@@ -0,0 +1,227 @@
+package(
+ default_visibility = ["//tensorflow:__subpackages__"],
+)
+
+licenses(["notice"]) # Apache 2.0
+
+load("//tensorflow:tensorflow.bzl", "tf_cc_test")
+
+cc_library(
+ name = "tfprof_stats",
+ srcs = ["tfprof_stats.cc"],
+ hdrs = ["tfprof_stats.h"],
+ deps = [
+ ":tfprof_graph",
+ ":tfprof_node",
+ ":tfprof_options",
+ ":tfprof_scope",
+ ":tfprof_show",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+cc_library(
+ name = "tfprof_node",
+ srcs = ["tfprof_node.cc"],
+ hdrs = ["tfprof_node.h"],
+ deps = [
+ ":tfprof_options",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+cc_library(
+ name = "tfprof_scope",
+ srcs = ["tfprof_scope.cc"],
+ hdrs = ["tfprof_scope.h"],
+ deps = [
+ ":tfprof_constants",
+ ":tfprof_node",
+ ":tfprof_options",
+ ":tfprof_show",
+ ":tfprof_tensor",
+ ":tfprof_utils",
+ "//tensorflow/c:c_api",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:framework",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+cc_library(
+ name = "tfprof_graph",
+ srcs = ["tfprof_graph.cc"],
+ hdrs = ["tfprof_graph.h"],
+ deps = [
+ ":tfprof_constants",
+ ":tfprof_node",
+ ":tfprof_options",
+ ":tfprof_show",
+ ":tfprof_tensor",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+cc_library(
+ name = "tfprof_show",
+ srcs = ["tfprof_show.cc"],
+ hdrs = ["tfprof_show.h"],
+ deps = [
+ ":tfprof_constants",
+ ":tfprof_node",
+ ":tfprof_options",
+ ":tfprof_tensor",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+tf_cc_test(
+ name = "tfprof_show_test",
+ srcs = ["tfprof_show_test.cc"],
+ data = [
+ "testdata/ckpt",
+ "testdata/graph.pbtxt",
+ "testdata/run_meta",
+ "testdata/tfprof_log",
+ ],
+ deps = [
+ ":tfprof_constants",
+ ":tfprof_options",
+ ":tfprof_stats",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ "//tensorflow/core:test",
+ "//tensorflow/core:test_main",
+ "//tensorflow/core:testlib",
+ ],
+)
+
+cc_library(
+ name = "tfprof_utils",
+ srcs = ["tfprof_utils.cc"],
+ hdrs = ["tfprof_utils.h"],
+ deps = [
+ ":tfprof_options",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+cc_library(
+ name = "tfprof_options",
+ srcs = ["tfprof_options.cc"],
+ hdrs = ["tfprof_options.h"],
+ deps = [
+ "//tensorflow/core:framework_headers_lib",
+ "//tensorflow/core:lib",
+ ],
+)
+
+cc_library(
+ name = "print_model_analysis",
+ srcs = ["print_model_analysis.cc"],
+ hdrs = ["print_model_analysis.h"],
+ deps = [
+ ":tfprof_options",
+ ":tfprof_stats",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ ],
+)
+
+tf_cc_test(
+ name = "tfprof_stats_test",
+ srcs = ["tfprof_stats_test.cc"],
+ data = [
+ "testdata/ckpt",
+ "testdata/graph.pbtxt",
+ "testdata/run_meta",
+ "testdata/tfprof_log",
+ ],
+ deps = [
+ ":tfprof_constants",
+ ":tfprof_options",
+ ":tfprof_stats",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ "//tensorflow/core:test",
+ "//tensorflow/core:test_main",
+ "//tensorflow/core:testlib",
+ ],
+)
+
+cc_library(
+ name = "tfprof_tensor",
+ srcs = ["tfprof_tensor.cc"],
+ hdrs = ["tfprof_tensor.h"],
+ deps = [
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:framework",
+ "//tensorflow/core:lib",
+ ],
+)
+
+tf_cc_test(
+ name = "tfprof_tensor_test",
+ srcs = ["tfprof_tensor_test.cc"],
+ data = [
+ "testdata/ckpt",
+ "testdata/graph.pbtxt",
+ ],
+ deps = [
+ ":tfprof_options",
+ ":tfprof_stats",
+ ":tfprof_utils",
+ "//tensorflow/c:checkpoint_reader",
+ "//tensorflow/contrib/tfprof/tools/tfprof:protos_all_cc",
+ "//tensorflow/core:lib",
+ "//tensorflow/core:protos_all_cc",
+ "//tensorflow/core:test",
+ "//tensorflow/core:test_main",
+ "//tensorflow/core:testlib",
+ ],
+)
+
+cc_library(
+ name = "tfprof_constants",
+ hdrs = ["tfprof_constants.h"],
+ deps = [
+ ],
+)
+# -----------------------------------------------------------------------------
+# Google-internal targets. These must be at the end for syncrepo.
+
+filegroup(
+ name = "all_files",
+ srcs = glob(
+ ["**/*"],
+ exclude = [
+ "**/METADATA",
+ "**/OWNERS",
+ ],
+ ),
+ visibility = ["//tensorflow:__subpackages__"],
+)
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.cc b/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.cc
new file mode 100644
index 00000000000..ab1e47b32dd
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.cc
@@ -0,0 +1,65 @@
+/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.h"
+
+#include
+#include
+#include
+
+#include "tensorflow/c/checkpoint_reader.h"
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_stats.h"
+
+namespace tensorflow {
+namespace tfprof {
+string PrintModelAnalysis(const string* graph, const string* run_meta,
+ const string* op_log, const string* command,
+ const Options* options) {
+ CHECK(graph) << "graph mustn't be null";
+ CHECK(command) << "command mustn't be null";
+ CHECK(options) << "options mustn't be null";
+ std::unique_ptr graph_ptr(new GraphDef());
+ graph_ptr->ParseFromString(*graph);
+
+ std::unique_ptr run_meta_ptr;
+ if (run_meta) {
+ run_meta_ptr.reset(new RunMetadata());
+ run_meta_ptr->ParseFromString(*run_meta);
+ }
+
+ std::unique_ptr op_log_ptr;
+ if (op_log) {
+ op_log_ptr.reset(new OpLog());
+ op_log_ptr->ParseFromString(*op_log);
+ }
+
+ std::unique_ptr ckpt_reader;
+
+ TFStats tf_stats(std::move(graph_ptr), std::move(run_meta_ptr),
+ std::move(op_log_ptr), std::move(ckpt_reader));
+
+ if (options->dump_to_file.empty()) {
+ printf("\n=========================Options=============================\n");
+ printf("%s", options->ToString().c_str());
+ printf("\n==================Model Analysis Report======================\n");
+ TFProfNode root(tf_stats.PrintGraph(*command, *options));
+ printf("\n======================End of Report==========================\n");
+ fflush(stdout);
+ return root.SerializeAsString();
+ }
+ return tf_stats.PrintGraph(*command, *options).SerializeAsString();
+}
+} // namespace tfprof
+} // namespace tensorflow
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.h b/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.h
new file mode 100644
index 00000000000..579147f1641
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/print_model_analysis.h
@@ -0,0 +1,45 @@
+/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_PRINT_MODEL_ANALYSIS_H_
+#define THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_PRINT_MODEL_ANALYSIS_H_
+
+#include
+
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_options.h"
+#include "tensorflow/contrib/tfprof/tools/tfprof/tfprof_log.pb.h"
+#include "tensorflow/contrib/tfprof/tools/tfprof/tfprof_output.pb.h"
+#include "tensorflow/core/framework/graph.pb.h"
+#include "tensorflow/core/lib/core/errors.h"
+#include "tensorflow/core/protobuf/config.pb.h"
+
+namespace tensorflow {
+namespace tfprof {
+
+// ***This API is only for swig.***
+//
+// Interface defined for Python API swig. Calls the tfprof core API.
+// 'graph', 'run_meta', 'op_log' are serialized GraphDef, RunMetadata,
+// OpLog strings, respectively.
+// 'graph', 'command' and 'options' are required. Others can be nullptr
+// if not available.
+string PrintModelAnalysis(const string* graph, const string* run_meta,
+ const string* op_log, const string* command,
+ const Options* options);
+
+} // namespace tfprof
+} // namespace tensorflow
+
+#endif // THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_PRINT_MODEL_ANALYSIS_H_
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/ckpt b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/ckpt
new file mode 100644
index 00000000000..2f59f071c59
Binary files /dev/null and b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/ckpt differ
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/graph.pbtxt b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/graph.pbtxt
new file mode 100644
index 00000000000..fd54551776c
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/graph.pbtxt
@@ -0,0 +1,636 @@
+node {
+ name: "zeros"
+ op: "Const"
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_FLOAT
+ tensor_shape {
+ dim {
+ size: 2
+ }
+ dim {
+ size: 6
+ }
+ dim {
+ size: 6
+ }
+ dim {
+ size: 3
+ }
+ }
+ float_val: 0.0
+ }
+ }
+ }
+}
+node {
+ name: "DW"
+ op: "Variable"
+ attr {
+ key: "container"
+ value {
+ s: ""
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "shape"
+ value {
+ shape {
+ dim {
+ size: 3
+ }
+ dim {
+ size: 3
+ }
+ dim {
+ size: 3
+ }
+ dim {
+ size: 6
+ }
+ }
+ }
+ }
+ attr {
+ key: "shared_name"
+ value {
+ s: ""
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal/shape"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_INT32
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_INT32
+ tensor_shape {
+ dim {
+ size: 4
+ }
+ }
+ tensor_content: "\003\000\000\000\003\000\000\000\003\000\000\000\006\000\000\000"
+ }
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal/mean"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_FLOAT
+ tensor_shape {
+ }
+ float_val: 0.0
+ }
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal/stddev"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_FLOAT
+ tensor_shape {
+ }
+ float_val: 0.0010000000475
+ }
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal/RandomStandardNormal"
+ op: "RandomStandardNormal"
+ input: "DW/Initializer/random_normal/shape"
+ attr {
+ key: "T"
+ value {
+ type: DT_INT32
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "seed"
+ value {
+ i: 87654321
+ }
+ }
+ attr {
+ key: "seed2"
+ value {
+ i: 5
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal/mul"
+ op: "Mul"
+ input: "DW/Initializer/random_normal/RandomStandardNormal"
+ input: "DW/Initializer/random_normal/stddev"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+}
+node {
+ name: "DW/Initializer/random_normal"
+ op: "Add"
+ input: "DW/Initializer/random_normal/mul"
+ input: "DW/Initializer/random_normal/mean"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+}
+node {
+ name: "DW/Assign"
+ op: "Assign"
+ input: "DW"
+ input: "DW/Initializer/random_normal"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+ attr {
+ key: "use_locking"
+ value {
+ b: true
+ }
+ }
+ attr {
+ key: "validate_shape"
+ value {
+ b: true
+ }
+ }
+}
+node {
+ name: "DW/read"
+ op: "Identity"
+ input: "DW"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW"
+ }
+ }
+ }
+}
+node {
+ name: "Conv2D"
+ op: "Conv2D"
+ input: "zeros"
+ input: "DW/read"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "data_format"
+ value {
+ s: "NHWC"
+ }
+ }
+ attr {
+ key: "padding"
+ value {
+ s: "SAME"
+ }
+ }
+ attr {
+ key: "strides"
+ value {
+ list {
+ i: 1
+ i: 2
+ i: 2
+ i: 1
+ }
+ }
+ }
+ attr {
+ key: "use_cudnn_on_gpu"
+ value {
+ b: true
+ }
+ }
+}
+node {
+ name: "DW2"
+ op: "Variable"
+ attr {
+ key: "container"
+ value {
+ s: ""
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "shape"
+ value {
+ shape {
+ dim {
+ size: 2
+ }
+ dim {
+ size: 2
+ }
+ dim {
+ size: 6
+ }
+ dim {
+ size: 12
+ }
+ }
+ }
+ }
+ attr {
+ key: "shared_name"
+ value {
+ s: ""
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal/shape"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_INT32
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_INT32
+ tensor_shape {
+ dim {
+ size: 4
+ }
+ }
+ tensor_content: "\002\000\000\000\002\000\000\000\006\000\000\000\014\000\000\000"
+ }
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal/mean"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_FLOAT
+ tensor_shape {
+ }
+ float_val: 0.0
+ }
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal/stddev"
+ op: "Const"
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "value"
+ value {
+ tensor {
+ dtype: DT_FLOAT
+ tensor_shape {
+ }
+ float_val: 0.0010000000475
+ }
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal/RandomStandardNormal"
+ op: "RandomStandardNormal"
+ input: "DW2/Initializer/random_normal/shape"
+ attr {
+ key: "T"
+ value {
+ type: DT_INT32
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+ attr {
+ key: "dtype"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "seed"
+ value {
+ i: 87654321
+ }
+ }
+ attr {
+ key: "seed2"
+ value {
+ i: 15
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal/mul"
+ op: "Mul"
+ input: "DW2/Initializer/random_normal/RandomStandardNormal"
+ input: "DW2/Initializer/random_normal/stddev"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+}
+node {
+ name: "DW2/Initializer/random_normal"
+ op: "Add"
+ input: "DW2/Initializer/random_normal/mul"
+ input: "DW2/Initializer/random_normal/mean"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+}
+node {
+ name: "DW2/Assign"
+ op: "Assign"
+ input: "DW2"
+ input: "DW2/Initializer/random_normal"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+ attr {
+ key: "use_locking"
+ value {
+ b: true
+ }
+ }
+ attr {
+ key: "validate_shape"
+ value {
+ b: true
+ }
+ }
+}
+node {
+ name: "DW2/read"
+ op: "Identity"
+ input: "DW2"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "_class"
+ value {
+ list {
+ s: "loc:@DW2"
+ }
+ }
+ }
+}
+node {
+ name: "Conv2D_1"
+ op: "Conv2D"
+ input: "Conv2D"
+ input: "DW2/read"
+ attr {
+ key: "T"
+ value {
+ type: DT_FLOAT
+ }
+ }
+ attr {
+ key: "data_format"
+ value {
+ s: "NHWC"
+ }
+ }
+ attr {
+ key: "padding"
+ value {
+ s: "SAME"
+ }
+ }
+ attr {
+ key: "strides"
+ value {
+ list {
+ i: 1
+ i: 2
+ i: 2
+ i: 1
+ }
+ }
+ }
+ attr {
+ key: "use_cudnn_on_gpu"
+ value {
+ b: true
+ }
+ }
+}
+versions {
+ producer: 13
+}
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/run_meta b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/run_meta
new file mode 100644
index 00000000000..2d5bb7ddaff
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/run_meta
@@ -0,0 +1,22 @@
+
+
+
+%/job:localhost/replica:0/task:0/cpu:0:
+_SOURCE (2
+cpuB_SOURCE = NoOp()H塈a
+zeros (2
+cpu:(&"cpu0Bzeros = Const()H^
+DW (2
+cpu:(&"cpu0ੀBDW = Variable()H`
+DW2 (2
+cpu:(&" cpu0BDW2 = Variable()Hj
+DW/read (2
+cpu:(&"cpu0ੀBDW/read = Identity(DW)Hm
+DW2/read (2
+cpu:(&" cpu0BDW2/read = Identity(DW2)Hs
+Conv2D P(U2
+cpu:(&"cpu0ીBConv2D = Conv2D(zeros, DW/read)H{
+Conv2D_1 (2
+cpu:(&"cpu0B#Conv2D_1 = Conv2D(Conv2D, DW2/read)H6
+_SINK (2
+cpuB_SINK = NoOp()H
\ No newline at end of file
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/tfprof_log b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/tfprof_log
new file mode 100644
index 00000000000..c35d4338e97
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/testdata/tfprof_log
@@ -0,0 +1,9 @@
+
+
+Conv2D_1$
+
+DW2_trainable_variables
+
+DW_trainable_variables
+
+Conv2D-
\ No newline at end of file
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_constants.h b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_constants.h
new file mode 100644
index 00000000000..169ebae4a75
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_constants.h
@@ -0,0 +1,37 @@
+/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#ifndef THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_TFPROF_CONSTANTS_H_
+#define THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_TFPROF_CONSTANTS_H_
+
+namespace tensorflow {
+namespace tfprof {
+
+// Op name of root of everything. Aggregates all stats.
+static const char* const kTFProfRoot = "_TFProfRoot";
+// Op type for nodes that doesn't represent a physical node in the
+// TensorFlow model. Only exist as a placehold to aggregate children.
+// For example, kTFProfRoot belongs to this type.
+static const char* const kTFGraphParent = "_TFGraphParent";
+static const char* const kTFScopeParent = "_kTFScopeParent";
+// Op type for tf.trainable_variables().
+static const char* const kTrainableVarType = "_trainable_variables";
+// Op type for tensors in the checkpoint file.
+static const char* const kCkptVarType = "_checkpoint_variables";
+
+} // namespace tfprof
+} // namespace tensorflow
+
+#endif // THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_TFPROF_CONSTANTS_H_
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.cc b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.cc
new file mode 100644
index 00000000000..287fd78d46c
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.cc
@@ -0,0 +1,222 @@
+/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.h"
+
+#include
+#include
+
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_constants.h"
+#include "tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_tensor.h"
+#include "tensorflow/core/lib/strings/strcat.h"
+#include "tensorflow/core/lib/strings/stringprintf.h"
+#include "tensorflow/core/platform/regexp.h"
+
+namespace tensorflow {
+namespace tfprof {
+GraphNode* TFGraph::CreateParentNode(const string& name) {
+ node_defs_.push_back(std::unique_ptr(new NodeDef()));
+ node_defs_.back()->set_name(name);
+ node_defs_.back()->set_op(kTFGraphParent);
+ parent_nodes_[name] =
+ std::unique_ptr(new TFNode(node_defs_.back().get()));
+ nodes_map_[name] =
+ std::unique_ptr(new GraphNode(parent_nodes_[name].get()));
+ return nodes_map_[name].get();
+}
+
+void TFGraph::AddNode(TFNode* node) {
+ string name = node->node_def()->name();
+ nodes_map_[name] = std::unique_ptr(new GraphNode(node));
+}
+
+void TFGraph::Build() {
+ if (!roots_.empty()) return;
+
+ std::set nonroots;
+ // Filter out the root nodes (node not input of any other node).
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ GraphNode* node = it->second.get();
+ const std::map& inputs = node->node->inputs();
+ for (auto inputs_it = inputs.cbegin(); inputs_it != inputs.cend();
+ inputs_it++) {
+ nonroots.insert(inputs_it->first);
+ auto child_it = nodes_map_.find(inputs_it->first);
+ if (child_it != nodes_map_.end()) {
+ node->children.push_back(child_it->second.get());
+ }
+ }
+ }
+ for (auto it = nodes_map_.begin(); it != nodes_map_.end(); it++) {
+ if (nonroots.find(it->first) == nonroots.end()) {
+ roots_.push_back(it->second.get());
+ }
+ }
+}
+
+const ShowNode* TFGraph::ShowInternal(const Options& opts) {
+ // Search the nodes to start from.
+ std::vector roots = roots_;
+ if (opts.start_name_regexes.size() != 1 ||
+ opts.start_name_regexes[0] != ".*") {
+ std::set visited;
+ roots = SearchRoot(roots, opts.start_name_regexes, &visited);
+ }
+
+ GraphNode* root = CreateParentNode(kTFProfRoot);
+ root->children.assign(roots.begin(), roots.end());
+
+ std::map account_visits;
+ Account({root}, opts, &account_visits);
+
+ if (opts.viz) {
+ printf("Visualizing feature disabled...\n");
+ }
+ std::set visits;
+ return PrintGraph({root}, opts, 1, 0, 0, &visits)[0];
+}
+
+std::vector TFGraph::SearchRoot(
+ const std::vector& roots, const std::vector& regexes,
+ std::set* visited) {
+ std::vector res;
+ if (roots.empty()) {
+ return res;
+ }
+ for (GraphNode* root : roots) {
+ if (visited->find(root->name()) != visited->end()) continue;
+ visited->insert(root->name());
+ // If the parent is a start point, don't search its children.
+ // Note that its children can still be added as start node through
+ // another route.
+ bool match_start_node = false;
+ for (const string& regex : regexes) {
+ if (RE2::FullMatch(root->name(), regex)) {
+ res.push_back(root);
+ match_start_node = true;
+ break;
+ }
+ }
+ if (match_start_node) {
+ continue;
+ }
+ std::vector nroot =
+ SearchRoot(root->children, regexes, visited);
+ res.insert(res.end(), nroot.begin(), nroot.end());
+ }
+ return res;
+}
+
+std::vector TFGraph::PrintGraph(const std::vector roots,
+ const Options& opts, int depth,
+ int hidden, int last_ident,
+ std::set* visits) {
+ std::vector show_nodes;
+
+ for (GraphNode* node : roots) {
+ if (visits->find(node->name()) != visits->end()) continue;
+ visits->insert(node->name());
+
+ int nhidden = hidden;
+ int nlast_ident = last_ident;
+ bool show = ShouldShow(node, opts, depth);
+ if (show) {
+ node->formatted_str.clear();
+ if (opts.account_displayed_op_only) {
+ node->ResetTotalStats();
+ node->AddSelfToTotalStats();
+ }
+ nhidden = 0;
+ nlast_ident = (hidden && opts.select.find(kShown[4]) != opts.select.end()
+ ? last_ident + 4
+ : last_ident + 2);
+ } else {
+ ++nhidden;
+ }
+
+ std::vector show_cnodes;
+ if (!ShouldTrim(node, opts.trim_name_regexes)) {
+ show_cnodes = PrintGraph(node->children, opts, depth + 1, nhidden,
+ nlast_ident, visits);
+ }
+ if (show) {
+ show_cnodes = SortNodes(show_cnodes, opts);
+ string children_str;
+ for (GraphNode* sc : show_cnodes) {
+ children_str += sc->formatted_str;
+ node->mutable_proto()->add_children()->MergeFrom(sc->proto());
+ if (opts.account_displayed_op_only) {
+ node->AggregateTotalStats(sc);
+ }
+ }
+ if (hidden && opts.select.find(kShown[4]) != opts.select.end()) {
+ node->formatted_str = strings::Printf(
+ "%s...hidden %d...\n", string(last_ident, ' ').c_str(), hidden);
+ node->formatted_str +=
+ strings::Printf(" %s%s\n", string(last_ident, ' ').c_str(),
+ node->Format(opts).c_str());
+ } else {
+ node->formatted_str =
+ strings::Printf("%s%s\n", string(last_ident, ' ').c_str(),
+ node->Format(opts).c_str());
+ }
+ if (opts.select.find(kShown[5]) != opts.select.end()) {
+ std::unique_ptr tfprof_tensor;
+ if (LookUpCheckPoint(node->name(), &tfprof_tensor)) {
+ string value_str;
+ tfprof_tensor->Display(&value_str,
+ node->mutable_proto()->mutable_tensor_value());
+ node->formatted_str += value_str;
+ }
+ }
+
+ node->formatted_str += children_str;
+ show_nodes.push_back(node);
+ } else {
+ show_nodes.insert(show_nodes.end(), show_cnodes.begin(),
+ show_cnodes.end());
+ }
+ }
+ return show_nodes;
+}
+
+void TFGraph::Account(const std::vector& roots, const Options& opts,
+ std::map* visits) {
+ if (roots.empty()) return;
+
+ for (GraphNode* node : roots) {
+ if (visits->find(node->name()) != visits->end()) continue;
+ (*visits)[node->name()] = 1;
+ node->ResetTotalStats();
+ // Depth-firsth.
+ Account(node->children, opts, visits);
+
+ node->account = ShouldAccount(node, opts);
+ if (node->account) {
+ node->AddSelfToTotalStats();
+ }
+ // Aggregate its children stats.
+ for (GraphNode* c : node->children) {
+ // A node can be visited from multiple parents. Only account once.
+ // "visits==1" is when the node is visited through depth-first search.
+ (*visits)[c->name()] += 1;
+ if ((*visits)[c->name()] > 2) continue;
+
+ node->AggregateTotalStats(c);
+ }
+ }
+}
+} // namespace tfprof
+} // namespace tensorflow
diff --git a/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.h b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.h
new file mode 100644
index 00000000000..ee54534f56b
--- /dev/null
+++ b/tensorflow/contrib/tfprof/tools/tfprof/internal/tfprof_graph.h
@@ -0,0 +1,116 @@
+/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+==============================================================================*/
+
+// Build a graph structure based on op inputs/outputs. The graph is a directed
+// acyclic graph pointing *from outputs to inputs*.
+
+#ifndef THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_TFPROF_GRAPH_H_
+#define THIRD_PARTY_TENSORFLOW_CONTRIB_TFPROF_TOOLS_TFPROF_INTERNAL_TFPROF_GRAPH_H_
+
+#include
+#include