| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7fffdb2 commit 1e8d1fe
12 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -123,6 +123,7 @@ tf_cuda_library( | |||
| 123 | 123 | linkstatic = 1, | |
| 124 | 124 | deps = [ | |
| 125 | 125 | ":debug_service_proto_cc", | |
| 126 | + ":debugger_event_metadata_proto_cc", | ||
| 126 | 127 | "//tensorflow/core:core_cpu_internal", | |
| 127 | 128 | "//tensorflow/core:framework", | |
| 128 | 129 | "//tensorflow/core:lib", | |
@@ -144,6 +145,7 @@ tf_cuda_library( | |||
| 144 | 145 | ":debug_graph_utils", | |
| 145 | 146 | ":debug_io_utils", | |
| 146 | 147 | ":debug_service_proto_cc", | |
| 148 | + ":debugger_event_metadata_proto_cc", | ||
| 147 | 149 | "//tensorflow/core:framework", | |
| 148 | 150 | "//tensorflow/core:lib", | |
| 149 | 151 | "//tensorflow/core:lib_internal", | |
@@ -194,6 +196,7 @@ tf_cc_test( | |||
| 194 | 196 | deps = [ | |
| 195 | 197 | ":debug_grpc_testlib", | |
| 196 | 198 | ":debug_io_utils", | |
| 199 | + ":debugger_event_metadata_proto_cc", | ||
| 197 | 200 | "//tensorflow/core:core_cpu", | |
| 198 | 201 | "//tensorflow/core:core_cpu_internal", | |
| 199 | 202 | "//tensorflow/core:framework", | |
@@ -204,6 +207,7 @@ tf_cc_test( | |||
| 204 | 207 | "//tensorflow/core:test", | |
| 205 | 208 | "//tensorflow/core:test_main", | |
| 206 | 209 | "//tensorflow/core:testlib", | |
| 210 | + "//tensorflow/core/platform/default/build_config:platformlib", | ||
| 207 | 211 | ], | |
| 208 | 212 | ) | |
| 209 | 213 | ||
@@ -247,6 +251,12 @@ tf_cc_test( | |||
| 247 | 251 | ], | |
| 248 | 252 | ) | |
| 249 | 253 | ||
| 254 | + tf_proto_library_cc( | ||
| 255 | + name = "debugger_event_metadata_proto", | ||
| 256 | + srcs = ["debugger_event_metadata.proto"], | ||
| 257 | + cc_api_version = 2, | ||
| 258 | + ) | ||
| 259 | + | ||
| 250 | 260 | # TODO(cais): Add the following back in when tfdbg is supported on Android. | |
| 251 | 261 | # filegroup( | |
| 252 | 262 | # name = "android_srcs", | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -16,10 +16,12 @@ limitations under the License. | |||
| 16 | 16 | #include "tensorflow/core/debug/debug_grpc_testlib.h" | |
| 17 | 17 | ||
| 18 | 18 | #include "tensorflow/core/debug/debug_graph_utils.h" | |
| 19 | + #include "tensorflow/core/debug/debugger_event_metadata.pb.h" | ||
| 19 | 20 | #include "tensorflow/core/framework/summary.pb.h" | |
| 20 | 21 | #include "tensorflow/core/lib/io/path.h" | |
| 21 | 22 | #include "tensorflow/core/lib/strings/str_util.h" | |
| 22 | 23 | #include "tensorflow/core/platform/env.h" | |
| 24 | + #include "tensorflow/core/platform/protobuf.h" | ||
| 23 | 25 | #include "tensorflow/core/platform/tracing.h" | |
| 24 | 26 | ||
| 25 | 27 | namespace tensorflow { | |
@@ -44,8 +46,6 @@ ::grpc::Status TestEventListenerImpl::SendEvents( | |||
| 44 | 46 | tensorflow::str_util::Split(val.node_name(), ':'); | |
| 45 | 47 | ||
| 46 | 48 | const string node_name = name_items[0]; | |
| 47 | - int32 output_slot = 0; | ||
| 48 | - tensorflow::strings::safe_strto32(name_items[1], &output_slot); | ||
| 49 | 49 | const string debug_op = name_items[2]; | |
| 50 | 50 | ||
| 51 | 51 | const TensorProto& tensor_proto = val.tensor(); | |
@@ -54,9 +54,24 @@ ::grpc::Status TestEventListenerImpl::SendEvents( | |||
| 54 | 54 | return ::grpc::Status::CANCELLED; | |
| 55 | 55 | } | |
| 56 | 56 | ||
| 57 | - device_names.push_back(val.tag()); | ||
| 57 | + // Obtain the device name, which is encoded in JSON. | ||
| 58 | + third_party::tensorflow::core::debug::DebuggerEventMetadata metadata; | ||
| 59 | + for (int i = 0; i < val.metadata().plugin_data_size(); i++) { | ||
| 60 | + if (val.metadata().plugin_data(i).plugin_name() != "debugger") { | ||
| 61 | + // This plugin data was meant for another plugin. | ||
| 62 | + continue; | ||
| 63 | + } | ||
| 64 | + auto status = tensorflow::protobuf::util::JsonStringToMessage( | ||
| 65 | + val.metadata().plugin_data(i).content(), &metadata); | ||
| 66 | + if (status.ok()) { | ||
| 67 | + // The device name has been determined. | ||
| 68 | + break; | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + device_names.push_back(metadata.device()); | ||
| 58 | 73 | node_names.push_back(node_name); | |
| 59 | - output_slots.push_back(output_slot); | ||
| 74 | + output_slots.push_back(metadata.output_slot()); | ||
| 60 | 75 | debug_ops.push_back(debug_op); | |
| 61 | 76 | debug_tensors.push_back(tensor); | |
| 62 | 77 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -26,11 +26,13 @@ limitations under the License. | |||
| 26 | 26 | #pragma comment(lib,"Ws2_32.lib") | |
| 27 | 27 | #endif | |
| 28 | 28 | ||
| 29 | + #include "tensorflow/core/debug/debugger_event_metadata.pb.h" | ||
| 29 | 30 | #include "tensorflow/core/framework/summary.pb.h" | |
| 30 | 31 | #include "tensorflow/core/lib/hash/hash.h" | |
| 31 | 32 | #include "tensorflow/core/lib/io/path.h" | |
| 32 | 33 | #include "tensorflow/core/lib/strings/str_util.h" | |
| 33 | 34 | #include "tensorflow/core/lib/strings/stringprintf.h" | |
| 35 | + #include "tensorflow/core/platform/protobuf.h" | ||
| 34 | 36 | #include "tensorflow/core/util/event.pb.h" | |
| 35 | 37 | ||
| 36 | 38 | #define GRPC_OSS_UNIMPLEMENTED_ERROR \ | |
@@ -55,7 +57,32 @@ Event WrapTensorAsEvent(const DebugNodeKey& debug_node_key, | |||
| 55 | 57 | // "DebugIdentity", the debug node_name in the Summary proto will be | |
| 56 | 58 | // "foo/node_a:0:DebugIdentity". | |
| 57 | 59 | summ_val->set_node_name(debug_node_key.debug_node_name); | |
| 58 | - summ_val->set_tag(debug_node_key.device_name); | ||
| 60 | + | ||
| 61 | + // Tag by the node name. This allows TensorBoard to quickly fetch data per op. | ||
| 62 | + summ_val->set_tag(debug_node_key.node_name); | ||
| 63 | + | ||
| 64 | + // Store data within debugger metadata to be stored for each event. | ||
| 65 | + third_party::tensorflow::core::debug::DebuggerEventMetadata metadata; | ||
| 66 | + metadata.set_device(debug_node_key.device_name); | ||
| 67 | + metadata.set_output_slot(debug_node_key.output_slot); | ||
| 68 | + | ||
| 69 | + // Encode the data in JSON. | ||
| 70 | + string json_output; | ||
| 71 | + tensorflow::protobuf::util::JsonPrintOptions json_options; | ||
| 72 | + json_options.always_print_primitive_fields = true; | ||
| 73 | + auto status = tensorflow::protobuf::util::MessageToJsonString( | ||
| 74 | + metadata, &json_output, json_options); | ||
| 75 | + if (status.ok()) { | ||
| 76 | + // Store summary metadata. Set the plugin to use this data as "debugger". | ||
| 77 | + SummaryMetadata::PluginData* plugin_data = | ||
| 78 | + summ_val->mutable_metadata()->add_plugin_data(); | ||
| 79 | + plugin_data->set_plugin_name("debugger"); | ||
| 80 | + plugin_data->set_content(json_output); | ||
| 81 | + } else { | ||
| 82 | + LOG(WARNING) << "Failed to convert DebuggerEventMetadata proto to JSON. " | ||
| 83 | + << "The debug_node_name is " << debug_node_key.debug_node_name | ||
| 84 | + << "."; | ||
| 85 | + } | ||
| 59 | 86 | ||
| 60 | 87 | if (tensor.dtype() == DT_STRING) { | |
| 61 | 88 | // Treat DT_STRING specially, so that tensor_util.MakeNdarray can convert | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,6 +15,7 @@ limitations under the License. | |||
| 15 | 15 | ||
| 16 | 16 | #include "tensorflow/core/debug/debug_io_utils.h" | |
| 17 | 17 | ||
| 18 | + #include "tensorflow/core/debug/debugger_event_metadata.pb.h" | ||
| 18 | 19 | #include "tensorflow/core/framework/summary.pb.h" | |
| 19 | 20 | #include "tensorflow/core/framework/tensor_testutil.h" | |
| 20 | 21 | #include "tensorflow/core/lib/core/notification.h" | |
@@ -124,10 +125,18 @@ TEST_F(DebugIOUtilsTest, DumpStringTensorToFileSunnyDay) { | |||
| 124 | 125 | ||
| 125 | 126 | ASSERT_GE(wall_time, event.wall_time()); | |
| 126 | 127 | ASSERT_EQ(1, event.summary().value().size()); | |
| 127 | - ASSERT_EQ(kDebugNodeKey.device_name, event.summary().value(0).tag()); | ||
| 128 | + ASSERT_EQ(kDebugNodeKey.node_name, event.summary().value(0).tag()); | ||
| 128 | 129 | ASSERT_EQ(kDebugNodeKey.debug_node_name, | |
| 129 | 130 | event.summary().value(0).node_name()); | |
| 130 | 131 | ||
| 132 | + // Determine and validate some information from the metadata. | ||
| 133 | + third_party::tensorflow::core::debug::DebuggerEventMetadata metadata; | ||
| 134 | + auto status = tensorflow::protobuf::util::JsonStringToMessage( | ||
| 135 | + event.summary().value(0).metadata().plugin_data(0).content(), &metadata); | ||
| 136 | + ASSERT_TRUE(status.ok()); | ||
| 137 | + ASSERT_EQ(kDebugNodeKey.device_name, metadata.device()); | ||
| 138 | + ASSERT_EQ(kDebugNodeKey.output_slot, metadata.output_slot()); | ||
| 139 | + | ||
| 131 | 140 | Tensor b_prime(DT_STRING); | |
| 132 | 141 | ASSERT_TRUE(b_prime.FromProto(event.summary().value(0).tensor())); | |
| 133 | 142 | ||
@@ -229,10 +238,19 @@ TEST_F(DebugIOUtilsTest, PublishTensorToMultipleFileURLs) { | |||
| 229 | 238 | ||
| 230 | 239 | ASSERT_GE(wall_time, event.wall_time()); | |
| 231 | 240 | ASSERT_EQ(1, event.summary().value().size()); | |
| 232 | - ASSERT_EQ(kDebugNodeKey.device_name, event.summary().value(0).tag()); | ||
| 241 | + ASSERT_EQ(kDebugNodeKey.node_name, event.summary().value(0).tag()); | ||
| 233 | 242 | ASSERT_EQ(kDebugNodeKey.debug_node_name, | |
| 234 | 243 | event.summary().value(0).node_name()); | |
| 235 | 244 | ||
| 245 | + // Determine and validate some information from the metadata. | ||
| 246 | + third_party::tensorflow::core::debug::DebuggerEventMetadata metadata; | ||
| 247 | + auto status = tensorflow::protobuf::util::JsonStringToMessage( | ||
| 248 | + event.summary().value(0).metadata().plugin_data(0).content(), | ||
| 249 | + &metadata); | ||
| 250 | + ASSERT_TRUE(status.ok()); | ||
| 251 | + ASSERT_EQ(kDebugNodeKey.device_name, metadata.device()); | ||
| 252 | + ASSERT_EQ(kDebugNodeKey.output_slot, metadata.output_slot()); | ||
| 253 | + | ||
| 236 | 254 | Tensor a_prime(DT_FLOAT); | |
| 237 | 255 | ASSERT_TRUE(a_prime.FromProto(event.summary().value(0).tensor())); | |
| 238 | 256 | ||
@@ -333,10 +351,19 @@ TEST_F(DebugIOUtilsTest, PublishTensorConcurrentlyToPartiallyOverlappingPaths) { | |||
| 333 | 351 | ||
| 334 | 352 | ASSERT_GE(wall_time, event.wall_time()); | |
| 335 | 353 | ASSERT_EQ(1, event.summary().value().size()); | |
| 336 | - ASSERT_EQ(kDebugNodeKey.device_name, event.summary().value(0).tag()); | ||
| 354 | + ASSERT_EQ(kDebugNodeKey.node_name, event.summary().value(0).tag()); | ||
| 337 | 355 | ASSERT_EQ(kDebugNodeKey.debug_node_name, | |
| 338 | 356 | event.summary().value(0).node_name()); | |
| 339 | 357 | ||
| 358 | + // Determine and validate some information from the metadata. | ||
| 359 | + third_party::tensorflow::core::debug::DebuggerEventMetadata metadata; | ||
| 360 | + auto status = tensorflow::protobuf::util::JsonStringToMessage( | ||
| 361 | + event.summary().value(0).metadata().plugin_data(0).content(), | ||
| 362 | + &metadata); | ||
| 363 | + ASSERT_TRUE(status.ok()); | ||
| 364 | + ASSERT_EQ(kDebugNodeKey.device_name, metadata.device()); | ||
| 365 | + ASSERT_EQ(kDebugNodeKey.output_slot, metadata.output_slot()); | ||
| 366 | + | ||
| 340 | 367 | Tensor a_prime(DT_FLOAT); | |
| 341 | 368 | ASSERT_TRUE(a_prime.FromProto(event.summary().value(0).tensor())); | |
| 342 | 369 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,9 @@ | |||
| 1 | + syntax = "proto3"; | ||
| 2 | + | ||
| 3 | + package third_party.tensorflow.core.debug; | ||
| 4 | + | ||
| 5 | + // Encapsulates per-event data related to debugging. | ||
| 6 | + message DebuggerEventMetadata { | ||
| 7 | + string device = 1; | ||
| 8 | + int32 output_slot = 2; | ||
| 9 | + }; | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -85,8 +85,15 @@ TEST_F(SummaryTensorOpV2Test, BasicPluginData) { | |||
| 85 | 85 | ASSERT_EQ(0, out_tensor->dims()); | |
| 86 | 86 | Summary summary; | |
| 87 | 87 | ParseProtoUnlimited(&summary, out_tensor->scalar<string>()()); | |
| 88 | - | ||
| 89 | 88 | ASSERT_EQ(1, summary.value_size()); | |
| 89 | + | ||
| 90 | + // Check the content of the tensor stored in the summary. | ||
| 91 | + Tensor string_content_tensor; | ||
| 92 | + CHECK(string_content_tensor.FromProto(summary.value(0).tensor())); | ||
| 93 | + ASSERT_EQ("some string tensor content", | ||
| 94 | + string_content_tensor.scalar<string>()()); | ||
| 95 | + | ||
| 96 | + // Check plugin-related data. | ||
| 90 | 97 | ASSERT_EQ("tag_foo", summary.value(0).tag()); | |
| 91 | 98 | ASSERT_EQ(2, summary.value(0).metadata().plugin_data_size()); | |
| 92 | 99 | ASSERT_EQ("foo", summary.value(0).metadata().plugin_data(0).plugin_name()); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -131,7 +131,6 @@ def _tensor_summary_v2( # pylint: disable=invalid-name | |||
| 131 | 131 | val = gen_logging_ops._tensor_summary_v2( | |
| 132 | 132 | tensor=tensor, | |
| 133 | 133 | tag=tag, | |
| 134 | - description="", | ||
| 135 | 134 | name=scope, | |
| 136 | 135 | serialized_summary_metadata=serialized_summary_metadata) | |
| 137 | 136 | summary_op_util.collect(val, collections, [ops.GraphKeys.SUMMARIES]) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -20,6 +20,7 @@ | |||
| 20 | 20 | @@FileWriter | |
| 21 | 21 | @@FileWriterCache | |
| 22 | 22 | @@tensor_summary | |
| 23 | + @@_tensor_summary_v2 | ||
| 23 | 24 | @@scalar | |
| 24 | 25 | @@histogram | |
| 25 | 26 | @@audio | |
@@ -28,6 +29,7 @@ | |||
| 28 | 29 | @@merge | |
| 29 | 30 | @@merge_all | |
| 30 | 31 | @@get_summary_description | |
| 32 | + @@PluginAsset | ||
| 31 | 33 | @@get_plugin_asset | |
| 32 | 34 | @@get_all_plugin_assets | |
| 33 | 35 | """ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -23,13 +23,26 @@ | |||
| 23 | 23 | from __future__ import division | |
| 24 | 24 | from __future__ import print_function | |
| 25 | 25 | ||
| 26 | + from collections import namedtuple | ||
| 26 | 27 | import json | |
| 27 | 28 | ||
| 29 | + from tensorflow.core.framework import summary_pb2 | ||
| 28 | 30 | from tensorflow.python.framework import dtypes | |
| 29 | - from tensorflow.python.ops.summary_ops import tensor_summary | ||
| 31 | + from tensorflow.python.ops.summary_ops import _tensor_summary_v2 | ||
| 30 | 32 | from tensorflow.python.summary import plugin_asset | |
| 33 | + from tensorflow.python.util import deprecation | ||
| 31 | 34 | ||
| 35 | + PLUGIN_NAME = "text" | ||
| 32 | 36 | ||
| 37 | + # Contains event-related data specific to the text plugin. | ||
| 38 | + _TextPluginData = namedtuple("_TextPluginData", []) | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + @deprecation.deprecated_args( | ||
| 42 | + "2017-06-13", | ||
| 43 | + "collections is deprecated. Instead of using collections to associate " | ||
| 44 | + "plugins to events, add a PluginData field to the SummaryMetadata of a " | ||
| 45 | + "Value proto.", "collections") | ||
| 33 | 46 | def text_summary(name, tensor, collections=None): | |
| 34 | 47 | """Summarizes textual data. | |
| 35 | 48 | ||
@@ -60,9 +73,16 @@ def text_summary(name, tensor, collections=None): | |||
| 60 | 73 | raise ValueError("Expected tensor %s to have dtype string, got %s" % | |
| 61 | 74 | (tensor.name, tensor.dtype)) | |
| 62 | 75 | ||
| 63 | - t_summary = tensor_summary(name, tensor, collections=collections) | ||
| 64 | - text_assets = plugin_asset.get_plugin_asset(TextSummaryPluginAsset) | ||
| 65 | - text_assets.register_tensor(t_summary.op.name) | ||
| 76 | + summary_metadata = summary_pb2.SummaryMetadata() | ||
| 77 | + text_plugin_data = _TextPluginData() | ||
| 78 | + data_dict = text_plugin_data._asdict() # pylint: disable=protected-access | ||
| 79 | + summary_metadata.plugin_data.add( | ||
| 80 | + plugin_name=PLUGIN_NAME, content=json.dumps(data_dict)) | ||
| 81 | + t_summary = _tensor_summary_v2( | ||
| 82 | + name=name, | ||
| 83 | + tensor=tensor, | ||
| 84 | + summary_metadata=summary_metadata, | ||
| 85 | + collections=collections) | ||
| 66 | 86 | return t_summary | |
| 67 | 87 | ||
| 68 | 88 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,7 +17,6 @@ | |||
| 17 | 17 | from __future__ import division | |
| 18 | 18 | from __future__ import print_function | |
| 19 | 19 | ||
| 20 | - from tensorflow.python.framework import ops as framework_ops | ||
| 21 | 20 | from tensorflow.python.framework import test_util | |
| 22 | 21 | from tensorflow.python.ops import array_ops | |
| 23 | 22 | from tensorflow.python.platform import googletest | |
@@ -43,16 +42,11 @@ def testTextSummaryAPI(self): | |||
| 43 | 42 | # The API accepts vectors. | |
| 44 | 43 | arr = array_ops.constant(["one", "two", "three"]) | |
| 45 | 44 | summ = text_summary.text_summary("foo", arr) | |
| 46 | - self.assertEqual(summ.op.type, "TensorSummary") | ||
| 45 | + self.assertEqual(summ.op.type, "TensorSummaryV2") | ||
| 47 | 46 | ||
| 48 | 47 | # the API accepts scalars | |
| 49 | 48 | summ = text_summary.text_summary("foo", array_ops.constant("one")) | |
| 50 | - self.assertEqual(summ.op.type, "TensorSummary") | ||
| 51 | - | ||
| 52 | - def testTextSummaryCollections(self): | ||
| 53 | - text_summary.text_summary("bar", array_ops.constant("2"), collections=[]) | ||
| 54 | - summaries = framework_ops.get_collection(framework_ops.GraphKeys.SUMMARIES) | ||
| 55 | - self.assertEqual(len(summaries), 0) | ||
| 49 | + self.assertEqual(summ.op.type, "TensorSummaryV2") | ||
| 56 | 50 | ||
| 57 | 51 | ||
| 58 | 52 | if __name__ == "__main__": | |
| Back | FazBrowse Home | New Git URL |
0 commit comments