Remove the __setattr__ override for Variables
authorAllen Lavoie <allenl@google.com>
Fri, 16 Feb 2018 21:46:47 +0000 (13:46 -0800)
committerTensorFlower Gardener <gardener@tensorflow.org>
Fri, 16 Feb 2018 21:50:47 +0000 (13:50 -0800)
Was slowing down the creation of _UnreadVariable objects. Adds CheckpointableBase without the __setattr__ override.

It's tempting to just override __setattr__ in variables to try making it faster, but it's already just doing an isinstance check. Removing the override entirely seems to be the cleanest option.

PiperOrigin-RevId: 186041147

15 files changed:
tensorflow/python/ops/variables.py
tensorflow/python/training/checkpointable.py
tensorflow/tools/api/golden/tensorflow.-variable.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-adadelta-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-adagrad-d-a-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-adagrad-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-adam-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-ftrl-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-gradient-descent-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-momentum-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-proximal-adagrad-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-proximal-gradient-descent-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-r-m-s-prop-optimizer.pbtxt
tensorflow/tools/api/golden/tensorflow.train.-sync-replicas-optimizer.pbtxt

index 125922e296414ebbcd22918ed4ff8858d56274fe..b785d0ede7433ab3105a3c865b998a8d19b6ea78 100644 (file)
@@ -37,7 +37,7 @@ from tensorflow.python.util.tf_export import tf_export
 
 
 @tf_export("Variable")
-class Variable(checkpointable.Checkpointable):
+class Variable(checkpointable.CheckpointableBase):
   """See the @{$variables$Variables How To} for a high level overview.
 
   A variable maintains state in the graph across calls to `run()`. You add a
index c2fea0f40d49e2a8e157bc498d25e4044cae3899..aaca67755ed6ac21d6d0e1d139a22f0aa4d4c5f8 100644 (file)
@@ -280,33 +280,13 @@ class _Checkpoint(object):
     self.session = session
 
 
-class Checkpointable(object):
-  """Manages dependencies on other objects.
+class CheckpointableBase(object):
+  """Base class for `Checkpointable` objects without automatic dependencies.
 
-  `Checkpointable` objects may have dependencies: other `Checkpointable` objects
-  which should be saved if the object declaring the dependency is saved. A
-  correctly saveable program has a dependency graph such that if changing a
-  global variable affects an object (e.g. changes the behavior of any of its
-  methods) then there is a chain of dependencies from the influenced object to
-  the variable.
-
-  Dependency edges have names, and are created implicitly when a
-  `Checkpointable` object is assigned to an attribute of another
-  `Checkpointable` object. For example:
-
-  ```
-  obj = Checkpointable()
-  obj.v = ResourceVariable(0.)
-  ```
-
-  The `Checkpointable` object `obj` now has a dependency named "v" on a
-  variable.
-
-  `Checkpointable` objects may specify `Tensor`s to be saved and restored
-  directly (e.g. a `Variable` indicating how to save itself) rather than through
-  dependencies on other objects. See
-  `Checkpointable._scatter_tensors_from_checkpoint` and
-  `Checkpointable._gather_tensors_for_checkpoint` for details.
+  This class has no __setattr__ override for performance reasons. Dependencies
+  must be added explicitly. Unless attribute assignment is performance-critical,
+  use `Checkpointable` instead. Use `CheckpointableBase` for `isinstance`
+  checks.
   """
 
   def _maybe_initialize_checkpointable(self):
@@ -333,21 +313,6 @@ class Checkpointable(object):
           "initialization code was run.")
     self._update_uid = -1
 
-  def __setattr__(self, name, value):
-    """Support self.foo = checkpointable syntax."""
-    # Perform the attribute assignment, and potentially call other __setattr__
-    # overrides such as that for tf.keras.Model.
-    super(Checkpointable, self).__setattr__(name, value)
-    if isinstance(value, Checkpointable):
-      self._track_checkpointable(
-          value, name=name,
-          # Allow the user to switch the Checkpointable which is tracked by this
-          # name, since assigning a new variable to an attribute has
-          # historically been fine (e.g. Adam did this).
-          # TODO(allenl): Should this be a warning once Checkpointable save/load
-          # is usable?
-          overwrite=True)
-
   def _add_variable_with_custom_getter(
       self, name, shape=None, dtype=dtypes.float32,
       initializer=None, getter=None, **kwargs_for_getter):
@@ -487,7 +452,7 @@ class Checkpointable(object):
       ValueError: If another object is already tracked by this name.
     """
     self._maybe_initialize_checkpointable()
-    if not isinstance(checkpointable, Checkpointable):
+    if not isinstance(checkpointable, CheckpointableBase):
       raise TypeError(
           ("Checkpointable._track_checkpointable() passed type %s, not a "
            "Checkpointable.") % (type(checkpointable),))
@@ -582,3 +547,48 @@ class Checkpointable(object):
   def _gather_tensors_for_checkpoint(self):
     """Returns a dictionary of Tensors to save with this object."""
     return {}
+
+
+class Checkpointable(CheckpointableBase):
+  """Manages dependencies on other objects.
+
+  `Checkpointable` objects may have dependencies: other `Checkpointable` objects
+  which should be saved if the object declaring the dependency is saved. A
+  correctly saveable program has a dependency graph such that if changing a
+  global variable affects an object (e.g. changes the behavior of any of its
+  methods) then there is a chain of dependencies from the influenced object to
+  the variable.
+
+  Dependency edges have names, and are created implicitly when a
+  `Checkpointable` object is assigned to an attribute of another
+  `Checkpointable` object. For example:
+
+  ```
+  obj = Checkpointable()
+  obj.v = ResourceVariable(0.)
+  ```
+
+  The `Checkpointable` object `obj` now has a dependency named "v" on a
+  variable.
+
+  `Checkpointable` objects may specify `Tensor`s to be saved and restored
+  directly (e.g. a `Variable` indicating how to save itself) rather than through
+  dependencies on other objects. See
+  `Checkpointable._scatter_tensors_from_checkpoint` and
+  `Checkpointable._gather_tensors_for_checkpoint` for details.
+  """
+
+  def __setattr__(self, name, value):
+    """Support self.foo = checkpointable syntax."""
+    # Perform the attribute assignment, and potentially call other __setattr__
+    # overrides such as that for tf.keras.Model.
+    super(Checkpointable, self).__setattr__(name, value)
+    if isinstance(value, CheckpointableBase):
+      self._track_checkpointable(
+          value, name=name,
+          # Allow the user to switch the Checkpointable which is tracked by this
+          # name, since assigning a new variable to an attribute has
+          # historically been fine (e.g. Adam did this).
+          # TODO(allenl): Should this be a warning once Checkpointable save/load
+          # is usable?
+          overwrite=True)
index 069200065a4ebe530fcc0c2f61e944d34f916224..5a02bb2175e2d6ad71722799143090f2735c1a37 100644 (file)
@@ -1,7 +1,7 @@
 path: "tensorflow.Variable"
 tf_class {
   is_instance: "<class \'tensorflow.python.ops.variables.Variable\'>"
-  is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "SaveSliceInfo"
index 4eea52596abfb42bedbd5aa7061aaddc496991e1..c02e54adfbd9f33e661453767b517a5f0de90d57 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.adadelta.AdadeltaOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 5aaaf0e20b7f77c130de856677dc7eee5d825fe9..2b619908fc6aea3f4b8e6a57d0dcf85a9854d466 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.adagrad_da.AdagradDAOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 7f1201879cc43d2a526ed65779ccd6a705812366..2005cf4677c06cf1f8b4207a444690fdd0c2306e 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.adagrad.AdagradOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 503c439d83379e8c36569bda55f3394eedcac8f9..0a2bae1d9021b20707e03ae5786e71f388266c14 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.adam.AdamOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 39c071748c5200115ed07f9b234b48552546ef10..847f9ad75998f1bdda8858650091c70fd0b4015b 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.ftrl.FtrlOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 6b441786ca17b98ab9aa5fd04af60372f2085921..13a58e0608ed269415ba78d84a03f1bae128e80c 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.gradient_descent.GradientDescentOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 80f3963bacdcdbe01eb4c77e18dc155f1e5ea682..bfbc2357a346c7bfef0242a735ab14c5f4005b22 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.momentum.MomentumOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index c880ba328a6b589e0bf0da8a010d417d5fc7c98a..437efa0a2bd04c308db6186e714a5d8785541fa5 100644 (file)
@@ -2,6 +2,7 @@ path: "tensorflow.train.Optimizer"
 tf_class {
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 6acdf35f786dc531a642f4280489bb9df3625b27..72f224605f67e72dd78699b5f1a703cc3edd566b 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.proximal_adagrad.ProximalAdagradOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 00b1e309e360f524283c746bb8499d970a62bbe7..316275b1fb1abd384e193994e35115a1c463f07d 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.proximal_gradient_descent.ProximalGradientDescentOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 05dc391cab99f982ef488eaf7231a9cd683b72b0..af50a1986100d830f0809a3f4a0f01faa8821b3b 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.rmsprop.RMSPropOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"
index 4be28192610a735d89b49c7e332e3135dce23eb8..6edc516c9392fa14f23ffc2a6481ec21216f06cf 100644 (file)
@@ -3,6 +3,7 @@ tf_class {
   is_instance: "<class \'tensorflow.python.training.sync_replicas_optimizer.SyncReplicasOptimizer\'>"
   is_instance: "<class \'tensorflow.python.training.optimizer.Optimizer\'>"
   is_instance: "<class \'tensorflow.python.training.checkpointable.Checkpointable\'>"
+  is_instance: "<class \'tensorflow.python.training.checkpointable.CheckpointableBase\'>"
   is_instance: "<type \'object\'>"
   member {
     name: "GATE_GRAPH"