Skip to content

Commit

Permalink
TensorFlow: upstream changes to git
Browse files Browse the repository at this point in the history
Change 109366961
	TensorFlow BUILD: now that we have an ops library,
	set linkstatic to 1. This fixes a breakage in the would-be
	opensource build, and it *might* mean we can get rid of
	all of the RequireDefaultOps() calls in our code.

	The ops library is much smaller than the kernels library that was
	previously linked together.  We set linkstatic=0 presumably since we
	didn't want to package a static copy of the kernels (very large)
	everywhere.  But the op definitions are small, so this seems like a
	safe change to make.  Time to build the various tests was not
	any longer after this change, and inspecting the example_trainer
	binary showed no large increase.
Change 109363613
	TensorFlow: new graph_def_builder_test needs to RequireDefaultOps.
Change 109362569
	Split ":ops" out of ":kernels" target in tensorflow/core.
Change 109360666
	Catch dtype and some shape errors sooner in `QueueBase`.

	Some avoidable errors were not being caught (e.g. the dtypes of the
	enqueue components were not checked against the queue's dtypes in
	Python), leading to cryptic messages at runtime. After this CL, they
	will be caught earlier.
Change 109359569
	TensorFlow: Expect g_ != nullptr in test
Change 109350735
	Add a version number to GraphDef

	We would like to be able to deprecate behavior in newly generated graphs
	without invalidating tensorflow's ability to read and evaluate old graphs.
	For this purpose, GraphDef now has a version field which can be checked inside
	op kernels to determine how backwards compatible to be.  version.h defines
	TF_GRAPHDEF_VERSION_MIN and TF_GRAPHDEF_VERSION_MAX specifying the range of
	supported GraphDef versions in the current version of tensorflow.

	Also expose tf.__version__ and tf.__graph_def_version{,_min,_max}__ for Python
	interrogation purposes.

	Whenever we want to deprecate or change some GraphDef semantics, we will
	proceed as follows:

	1. Bump TF_GRAPHDEF_VERSION_MAX, leaving TF_GRAPHDEF_VERSION_MIN unchanged.
	   Describe the change in graph.proto, include the date introduced.

	2. In each relevant kernel, implement the new behavior if the GraphDef version
	   is new, but preserve the old behavior for previous GraphDef versions.

	3. Wait six months or so (we need to formalize this somewhere).

	4. Bump TF_GRAPHDEF_VERSION_MIN and remove the backwards compatibility.

	The GraphDef version is distinct from the open source version, but at least
	(4) and possibly (1) correspond to major version number bumps.

	The first GraphDef version bump is the upcoming scalar strictness change,
	which affects Google users only since open source is already scalar strict.

	This commit does not yet plumb the version number into OpKernelConstruction
	so that ops can access it.  That will follow.
Change 109350260
	Made TensorShapeProto implicitly convertible to TensorShape.

Base CL: 109366982
  • Loading branch information
Vijay Vasudevan committed Dec 4, 2015
1 parent eb5e56e commit 54a644f
Show file tree
Hide file tree
Showing 33 changed files with 620 additions and 51 deletions.
41 changes: 31 additions & 10 deletions tensorflow/core/BUILD
Expand Up @@ -187,10 +187,7 @@ cc_library(
"graph/testlib.h",
],
copts = tf_copts(),
visibility = [
":friends",
"//tensorflow:internal",
],
visibility = ["//visibility:public"],
deps = [
":core_cpu",
":tensorflow",
Expand All @@ -213,11 +210,9 @@ tf_cuda_library(
)

tf_cuda_library(
name = "kernels",
name = "ops",
srcs = glob(
[
"kernels/**/*.h",
"kernels/**/*.cc",
"ops/**/*.h",
"ops/**/*.cc",
"user_ops/**/*.h",
Expand All @@ -226,25 +221,49 @@ tf_cuda_library(
exclude = [
"**/*test*",
"**/*main.cc",
"kernels/**/*.cu.cc",
"user_ops/**/*.cu.cc",
],
),
copts = tf_copts(),
linkstatic = 1,
visibility = ["//visibility:public"],
deps = [
":core",
":lib",
":protos_cc",
"//tensorflow/models/embedding:word2vec_ops",
"//third_party/eigen3",
],
alwayslink = 1,
)

tf_cuda_library(
name = "kernels",
srcs = glob(
[
"kernels/**/*.h",
"kernels/**/*.cc",
],
exclude = [
"**/*test*",
"**/*main.cc",
"kernels/**/*.cu.cc",
],
),
copts = tf_copts(),
cuda_deps = [
":gpu_kernels",
":cuda",
],
linkstatic = 0,
visibility = ["//visibility:public"],
deps = [
"@gemmlowp//:eight_bit_int_gemm",
":core",
":lib",
":ops",
":protos_cc",
":stream_executor",
"//tensorflow/models/embedding:word2vec_kernels",
"//tensorflow/models/embedding:word2vec_ops",
"//third_party/eigen3",
],
alwayslink = 1,
Expand All @@ -262,6 +281,7 @@ tf_gpu_kernel_library(
),
visibility = ["//visibility:public"],
deps = [
":cuda",
"//third_party/eigen3",
],
)
Expand Down Expand Up @@ -416,6 +436,7 @@ tf_cc_tests(
":direct_session",
":kernels",
":lib",
":ops",
":strict_headers",
":test_main",
":testlib",
Expand Down
5 changes: 5 additions & 0 deletions tensorflow/core/common_runtime/direct_session.cc
Expand Up @@ -164,6 +164,11 @@ Status DirectSession::Extend(const GraphDef& graph) {
}

Status DirectSession::ExtendLocked(const GraphDef& graph) {
if (graph_created_ && graph_def_.version() != graph.version()) {
return errors::InvalidArgument("Incompatible GraphDef versions in Extend: ",
graph_def_.version(), " != ",
graph.version());
}
graph_created_ = true; // In case this is first call
graph_def_.MergeFrom(graph);
return Status::OK();
Expand Down
1 change: 1 addition & 0 deletions tensorflow/core/common_runtime/function.cc
Expand Up @@ -980,6 +980,7 @@ static void ToGraphDef(const Graph* g, GraphDef* gdef) {
}
gtl::InlinedVector<const Edge*, 4> inputs;
gdef->Clear();
gdef->set_version(g->version());
while (!ready.empty()) {
const Node* n = ready.front();
ready.pop_front();
Expand Down
2 changes: 2 additions & 0 deletions tensorflow/core/framework/function_testlib.cc
Expand Up @@ -17,6 +17,7 @@ limitations under the License.

#include "tensorflow/core/framework/function.h"
#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/public/version.h"

namespace tensorflow {
namespace test {
Expand All @@ -27,6 +28,7 @@ typedef FunctionDefHelper FDH;
GraphDef GDef(gtl::ArraySlice<NodeDef> nodes,
gtl::ArraySlice<FunctionDef> funcs) {
GraphDef g;
g.set_version(TF_GRAPH_DEF_VERSION);
for (auto n : nodes) {
*(g.add_node()) = n;
}
Expand Down
11 changes: 11 additions & 0 deletions tensorflow/core/framework/graph.proto
Expand Up @@ -15,6 +15,17 @@ import "tensorflow/core/framework/function.proto";
message GraphDef {
repeated NodeDef node = 1;

// Compatibility version of the graph. Newly created graphs use
// the most recent version. Version history:
//
// 0. Graphs created before GraphDef versioning
// 1. First real version (2dec2015)
//
// The GraphDef version is distinct from the TensorFlow version.
// Each released version of TensorFlow will support a range of
// GraphDef versions.
int32 version = 3;

// EXPERIMENTAL. DO NOT USE OR DEPEND ON THIS YET.
//
// "library" provides user-defined functions.
Expand Down
1 change: 1 addition & 0 deletions tensorflow/core/framework/graph_def_util.cc
Expand Up @@ -24,6 +24,7 @@ namespace tensorflow {

string SummarizeGraphDef(const GraphDef& graph_def) {
string ret;
strings::StrAppend(&ret, "version = ", graph_def.version(), ";\n");
for (const NodeDef& node : graph_def.node()) {
strings::StrAppend(&ret, SummarizeNodeDef(node), ";\n");
}
Expand Down
8 changes: 8 additions & 0 deletions tensorflow/core/graph/equal_graph_def.cc
Expand Up @@ -26,6 +26,14 @@ namespace tensorflow {

bool EqualGraphDef(const GraphDef& actual, const GraphDef& expected,
string* diff) {
if (actual.version() != expected.version()) {
if (diff != nullptr) {
*diff = strings::StrCat("Expected version ", expected.version(),
", got version ", actual.version());
}
return false;
}

std::unordered_map<string, const NodeDef*> actual_index;
for (const NodeDef& node : actual.node()) {
actual_index[node.name()] = &node;
Expand Down
10 changes: 6 additions & 4 deletions tensorflow/core/graph/equal_graph_def_test.cc
Expand Up @@ -20,6 +20,7 @@ limitations under the License.
#include "tensorflow/core/framework/op.h"
#include "tensorflow/core/graph/graph_def_builder.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/public/version.h"

namespace tensorflow {
namespace {
Expand Down Expand Up @@ -88,10 +89,11 @@ TEST_F(EqualGraphDefTest, ExtraNode) {
Input(a_.opts().WithName("A"));
Input(a_.opts().WithName("B"));
EXPECT_FALSE(Match());
EXPECT_EQ(
"Found unexpected node 'B = Input[]()' not in expected graph:\n"
"A = Input[]();\n",
diff_);
EXPECT_EQ(strings::StrCat(
"Found unexpected node 'B = Input[]()' not in expected graph:\n"
"version = ",
TF_GRAPH_DEF_VERSION, ";\nA = Input[]();\n"),
diff_);
}

TEST_F(EqualGraphDefTest, NodeOrder) {
Expand Down
4 changes: 3 additions & 1 deletion tensorflow/core/graph/graph.cc
Expand Up @@ -21,6 +21,7 @@ limitations under the License.
#include "tensorflow/core/lib/gtl/map_util.h"
#include "tensorflow/core/lib/strings/strcat.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/public/version.h"

namespace tensorflow {

Expand Down Expand Up @@ -105,7 +106,7 @@ Node::Properties::~Properties() {}
// Graph

Graph::Graph(const OpRegistryInterface* ops)
: ops_(ops), arena_(8 << 10 /* 8kB */) {
: ops_(ops), version_(TF_GRAPH_DEF_VERSION), arena_(8 << 10 /* 8kB */) {
// Source and sink have no endpoints, just control edges.
NodeDef def;
def.set_name("_SOURCE");
Expand Down Expand Up @@ -253,6 +254,7 @@ void AddInput(NodeDef* dst, StringPiece src_name, int src_slot) {

void Graph::ToGraphDef(GraphDef* graph_def) const {
graph_def->Clear();
graph_def->set_version(version());
std::vector<const Edge*>
inputs; // Construct this outside the loop for speed.
for (const Node* node : nodes()) {
Expand Down
9 changes: 9 additions & 0 deletions tensorflow/core/graph/graph.h
Expand Up @@ -187,11 +187,17 @@ class Graph {
// single SINK (always id kSinkId) node, and an edge from SOURCE->SINK.
//
// The graph can hold ops found in registry.
//
// The version defaults to TF_GRAPH_DEF_VERSION.
explicit Graph(const OpRegistryInterface* registry);
~Graph();

static const int kControlSlot = -1;

// The GraphDef version of this graph (see graph.proto).
int version() const { return version_; }
void set_version(int version) { version_ = version; }

// Adds a new node to this graph, and returns it. Infers the Op and
// input/output types for the node. *this owns the returned instance.
// Returns nullptr and sets *status on error.
Expand Down Expand Up @@ -274,6 +280,9 @@ class Graph {
// Registry of all known ops. Not owned.
const OpRegistryInterface* const ops_;

// GraphDef version
int version_;

// Allocator which will give us good locality.
core::Arena arena_;

Expand Down
14 changes: 14 additions & 0 deletions tensorflow/core/graph/graph_constructor.cc
Expand Up @@ -29,6 +29,7 @@ limitations under the License.
#include "tensorflow/core/lib/gtl/inlined_vector.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/regexp.h"
#include "tensorflow/core/public/version.h"

namespace tensorflow {

Expand All @@ -45,6 +46,19 @@ class GraphConstructor {
GraphConstructor(const GraphConstructorOptions& opts, const GraphDef* gdef,
Graph* g, Status* status)
: opts_(opts), gdef_(gdef), g_(g), status_(status) {
const int version = gdef->version();
if (!(TF_GRAPH_DEF_VERSION_MIN <= version &&
version <= TF_GRAPH_DEF_VERSION_MAX)) {
bool low = version < TF_GRAPH_DEF_VERSION_MAX;
*status = errors::InvalidArgument(
"GraphDef version ", version, " is ", low ? "no longer" : "not yet",
" supported: TensorFlow ", TF_VERSION_STRING, " needs ",
TF_GRAPH_DEF_VERSION_MAX, " <= version <= ", TF_GRAPH_DEF_VERSION_MIN,
". ",
low ? "Please regenerate your graph." : "Please upgrade TensorFlow.");
return;
}
g->set_version(gdef->version());
BuildNodeIndex();
InitFromEdges();
Convert();
Expand Down
32 changes: 31 additions & 1 deletion tensorflow/core/graph/graph_constructor_test.cc
Expand Up @@ -24,6 +24,7 @@ limitations under the License.
#include "tensorflow/core/platform/protobuf.h"
#include "tensorflow/core/platform/regexp.h"
#include "tensorflow/core/public/status.h"
#include "tensorflow/core/public/version.h"

// TODO(josh11b): Test InitCostModel().
// TODO(josh11b): Test setting the "device" field of a NodeDef.
Expand Down Expand Up @@ -58,6 +59,12 @@ class GraphConstructorTest : public ::testing::Test {
TF_CHECK_OK(ConvertGraphDefToGraph(opts, gdef_, g_.get()));
}

void ExpectVersion(int version) {
EXPECT_NE(nullptr, g_);
EXPECT_EQ(version, g_->version()) << "Expected version " << version
<< ", got " << g_->version();
}

Node* FindNode(const string& name) {
for (Node* n : g_->nodes()) {
if (n->name() == name) return n;
Expand Down Expand Up @@ -160,7 +167,30 @@ TEST_F(GraphConstructorTest, TypeMismatch) {
"expected int32.");
}

TEST_F(GraphConstructorTest, EmptyGraph) { ExpectOK(""); }
TEST_F(GraphConstructorTest, EmptyGraph) {
ExpectOK("");
ExpectVersion(0); // The default GraphDef version is 0
}

TEST_F(GraphConstructorTest, VersionGraph) {
ASSERT_LT(0, TF_GRAPH_DEF_VERSION); // Verify the assertion is nontrivial
ExpectOK(strings::StrCat("version: ", TF_GRAPH_DEF_VERSION));
ExpectVersion(TF_GRAPH_DEF_VERSION);
}

TEST_F(GraphConstructorTest, LowVersion) {
ExpectError(strings::StrCat("version: ", -1),
R"(^GraphDef version -1 is no longer supported: TensorFlow \S+ )"
R"(needs \d+ <= version <= \d+\. )"
R"(Please regenerate your graph\.$)");
}

TEST_F(GraphConstructorTest, HighVersion) {
ExpectError(strings::StrCat("version: ", TF_GRAPH_DEF_VERSION_MAX + 1),
R"(^GraphDef version \d+ is not yet supported: TensorFlow \S+ )"
R"(needs \d+ <= version <= \d+\. )"
R"(Please upgrade TensorFlow\.$)");
}

TEST_F(GraphConstructorTest, SimpleModel) {
ExpectOK(
Expand Down
48 changes: 48 additions & 0 deletions tensorflow/core/graph/graph_def_builder_test.cc
@@ -0,0 +1,48 @@
/* Copyright 2015 Google Inc. 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/core/graph/graph_def_builder.h"

#include <gtest/gtest.h>
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/status_test_util.h"
#include "tensorflow/core/public/version.h"

namespace tensorflow {
namespace {

TEST(GraphDefBuilderTest, Version) {
RequireDefaultOps();

// Verify that our assertions will be nontrivial
ASSERT_LT(0, TF_GRAPH_DEF_VERSION);

// Newly built graphs should use the current version
GraphDefBuilder builder(GraphDefBuilder::kFailImmediately);

// Check version when we convert to a Graph
Graph graph(OpRegistry::Global());
EXPECT_OK(builder.ToGraph(&graph));
ASSERT_EQ(graph.version(), TF_GRAPH_DEF_VERSION);

// Check version when we convert to a GraphDef
GraphDef graph_def;
EXPECT_OK(builder.ToGraphDef(&graph_def));
ASSERT_EQ(graph_def.version(), TF_GRAPH_DEF_VERSION);
}

} // namespace
} // namespace tensorflow
5 changes: 5 additions & 0 deletions tensorflow/core/graph/graph_partition.cc
Expand Up @@ -1051,6 +1051,11 @@ Status Partition(const PartitionOptions& opts, Graph* g,
}
}

// Set versions
for (auto& it : *partitions) {
it.second.set_version(g->version());
}

// Set the start times for recvs at the very end.
if (opts.scheduling_for_recvs) {
for (auto& it : dup_recv) {
Expand Down

0 comments on commit 54a644f

Please sign in to comment.