如何有效跟踪张量流张量的历史?

时间:2019-07-09 21:02:39

标签: python-3.x tensorflow tensorflow2.0

这种使用TensorArray的模式是跟踪张量历史的有效方法吗?是否在GPU上完成了内部循环中的所有操作而没有将任何内容传输给CPU?我该如何验证?

import tensorflow as tf


with tf.device('/device:GPU:0'):
    @tf.function
    def f(x, y):
        return y, x + y

    x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
                             clear_after_read=False)
    y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
                             clear_after_read=False)

    x = tf.Variable([1.0])
    y = tf.Variable([1.0])
    x_array.write(0, x)
    y_array.write(0, y)

    for i in tf.range(10):
        x = x_array.read(i)
        y = y_array.read(i)
        new_x, new_y = f(x, y)
        x_array.write(i + 1, new_x)
        y_array.write(i + 1, new_y)

    print(x_array.stack())
    print(y_array.stack())

这实际上是我想要做的,但是它甚至没有运行:

import tensorflow as tf


with tf.device('/device:GPU:0'):
    @tf.function
    def f(x, y):
        return y, x + y

    @tf.function
    def g(n):
        for i in tf.range(n):
            x = x_array.read(i)
            y = y_array.read(i)
            new_x, new_y = f(x, y)
            x_array.write(i + 1, new_x)
            y_array.write(i + 1, new_y)

    x_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
                             clear_after_read=False)
    y_array = tf.TensorArray(tf.float32, 0, dynamic_size=True,
                             clear_after_read=False)

    x = tf.Variable([1.0])
    y = tf.Variable([1.0])
    x_array.write(0, x)
    y_array.write(0, y)

    g(tf.constant(10))

    print(x_array.stack())
    print(y_array.stack())

1 个答案:

答案 0 :(得分:1)

您可以在此处修复第二个片段:

import tensorflow as tf

with tf.device('/device:GPU:0'):
    @tf.function
    def f(x, y):
        return y, x + y

    @tf.function
    def g(x, y, n):
        x_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
                                 clear_after_read=True)
        y_array = tf.TensorArray(tf.float32, n + 1, dynamic_size=False,
                                 clear_after_read=True)
        x_array = x_array.write(0, x)
        y_array = y_array.write(0, y)
        for i in range(n):
            x, y = f(x, y)
            x_array = x_array.write(i + 1, x)
            y_array = y_array.write(i + 1, y)
        return x_array.stack(), y_array.stack()


    x = tf.Variable([1.0])
    y = tf.Variable([1.0])

    x_hist, y_hist = g(x, y, tf.constant(10))

    print(x_hist)
    # tf.Tensor(
    # [[ 1.]
    #  [ 1.]
    #  [ 2.]
    #  [ 3.]
    #  [ 5.]
    #  [ 8.]
    #  [13.]
    #  [21.]
    #  [34.]
    #  [55.]
    #  [89.]], shape=(11, 1), dtype=float32)
    print(y_hist)
    # tf.Tensor(
    # [[  1.]
    #  [  2.]
    #  [  3.]
    #  [  5.]
    #  [  8.]
    #  [ 13.]
    #  [ 21.]
    #  [ 34.]
    #  [ 55.]
    #  [ 89.]
    #  [144.]], shape=(11, 1), dtype=float32)

有一些问题。 tf.function应该以其输入作为参数,而不是来自全局范围。您可以在函数中创建张量数组,并且可以使它们固定大小并具有读取后清除的功能,因为您将不使用它们。但是,将每个write操作的结果分配给数组变量很重要,因为那样会使它成为“写入后的张量数组”。您无需在循环中使用tf.range。而且,只需编写每次迭代的结果,而不用再次读取该数组,即可更有效地填充“历史”数组。

关于GPU,由于所有内容都在tf.device上下文中,因此所有内容都将在GPU上分配并运行,如果某些内容无法在GPU上运行,则将出现错误,因此只要所有内容都可以运行很好。