Skip to content

Commit 601bd3f

Browse files
ebrevdotensorflower-gardener
authored andcommitted
Functional ops (fold*, map_fn) now make sure get_variable calls cache to local device.
This forces an I/O step on the first call always, but because the caching is local, any steps past the first will just use the cached variables. Reduces I/O for get_variable from O(N) to O(1). Similarly for gradients. Change: 118825794
1 parent f4a3fbc commit 601bd3f

1 file changed

Lines changed: 35 additions & 12 deletions

File tree

tensorflow/python/ops/functional_ops.py

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from tensorflow.python.ops import constant_op
3636
from tensorflow.python.ops import control_flow_ops
3737
from tensorflow.python.ops import tensor_array_ops
38+
from tensorflow.python.ops import variable_scope as vs
3839
# pylint: disable=wildcard-import
3940
from tensorflow.python.ops.gen_functional_ops import *
4041
# pylint: enable=wildcard-import
@@ -82,9 +83,15 @@ def foldl(fn, elems, initializer=None, parallel_iterations=10, back_prop=True,
8283
# sum == 21
8384
```
8485
"""
85-
with ops.op_scope([elems], name, "foldl") as name:
86-
if not callable(fn):
87-
raise TypeError("fn must be callable.")
86+
if not callable(fn):
87+
raise TypeError("fn must be callable.")
88+
89+
# TODO(ebrevdo): Change to using colocate_with here and in other methods.
90+
with vs.variable_op_scope([elems], name, "foldl") as varscope:
91+
# Any get_variable calls fn will cache the first call locally
92+
# and not issue repeated network I/O requests for each iteration.
93+
if varscope.caching_device is None:
94+
varscope.set_caching_device(lambda op: op.device)
8895

8996
# Convert elems to tensor array.
9097
n = array_ops.shape(elems)[0]
@@ -147,9 +154,14 @@ def foldr(fn, elems, initializer=None, parallel_iterations=10, back_prop=True,
147154
# sum == 21
148155
```
149156
"""
150-
with ops.op_scope([elems], name, "foldr") as name:
151-
if not callable(fn):
152-
raise TypeError("fn must be callable.")
157+
if not callable(fn):
158+
raise TypeError("fn must be callable.")
159+
160+
with vs.variable_op_scope([elems], name, "foldr") as varscope:
161+
# Any get_variable calls fn will cache the first call locally
162+
# and not issue repeated network I/O requests for each iteration.
163+
if varscope.caching_device is None:
164+
varscope.set_caching_device(lambda op: op.device)
153165

154166
# Convert elems to tensor array.
155167
n = array_ops.shape(elems)[0]
@@ -210,9 +222,15 @@ def map_fn(fn, elems, dtype=None, parallel_iterations=10, back_prop=True,
210222
# squares == [1, 4, 9, 16, 25, 36]
211223
```
212224
"""
213-
with ops.op_scope([elems], name, "map") as name:
214-
if not callable(fn):
215-
raise TypeError("fn must be callable.")
225+
if not callable(fn):
226+
raise TypeError("fn must be callable.")
227+
228+
with vs.variable_op_scope([elems], name, "map") as varscope:
229+
# Any get_variable calls fn will cache the first call locally
230+
# and not issue repeated network I/O requests for each iteration.
231+
if varscope.caching_device is None:
232+
varscope.set_caching_device(lambda op: op.device)
233+
216234
dtype = dtype if dtype else elems.dtype
217235

218236
# Convert elems to tensor array.
@@ -272,9 +290,14 @@ def scan(fn, elems, initializer=None, parallel_iterations=10, back_prop=True,
272290
# sum == [1, 3, 6, 10, 15, 21]
273291
```
274292
"""
275-
with ops.op_scope([elems], name, "scan") as name:
276-
if not callable(fn):
277-
raise TypeError("fn must be callable.")
293+
if not callable(fn):
294+
raise TypeError("fn must be callable.")
295+
296+
with vs.variable_op_scope([elems], name, "scan") as varscope:
297+
# Any get_variable calls fn will cache the first call locally
298+
# and not issue repeated network I/O requests for each iteration.
299+
if varscope.caching_device is None:
300+
varscope.set_caching_device(lambda op: op.device)
278301

279302
# Convert elems to tensor array.
280303
n = array_ops.shape(elems)[0]

0 commit comments

Comments
 (0)