Tensorflow:GPU 利用率几乎总是 0%
Tensorflow: GPU Utilization is almost always at 0%
我将 tensorflow 与 Titan-X GPU 一起使用,我注意到,当我 运行 CIFAR10 示例时,Volatile GPU-utilization
非常稳定地保持在 30% 左右,而当我训练时在我自己的模型中,Volatile GPU-utilization
远非稳定,它几乎总是 0%,在回到 0% 之前达到 80/90%,一遍又一遍。
我认为这种行为是由于我将数据馈送到网络的方式造成的(我在每一步之后获取数据,这需要一些时间)。但是在实现队列来提供数据并避免步骤之间的这种延迟之后,问题仍然存在(请参阅下面的队列系统)。
有什么想法吗?
batch = 128 # size of the batch
x = tf.placeholder("float32", [None, n_steps, n_input])
y = tf.placeholder("float32", [None, n_classes])
# with a capacity of 100 batches, the bottleneck should not be the data feeding
queue = tf.RandomShuffleQueue(capacity=100*batch,
min_after_dequeue=80*batch,
dtypes=[tf.float32, tf.float32],
shapes=[[n_steps, n_input], [n_classes]])
enqueue_op = queue.enqueue_many([x, y])
X_batch, Y_batch = queue.dequeue_many(batch)
sess = tf.Session()
def load_and_enqueue(data):
while True:
X, Y = data.get_next_batch(batch)
sess.run(enqueue_op, feed_dict={x: X, y: Y})
train_thread = threading.Thread(target=load_and_enqueue, args=(data))
train_thread.daemon = True
train_thread.start()
for _ in xrange(max_iter):
sess.run(train_op)
在做了一些实验之后,我找到了答案,所以我 post 因为它可能对其他人有用。
首先,get_next_batch
比 train_op
慢大约 15 倍(感谢 Eric Platon 指出这一点)。
但是,我认为队列正在被填充到 capacity
,并且只有在训练应该开始之后。因此,我认为即使 get_next_batch
慢得多,队列也应该隐藏这种延迟,至少在开始时,因为它包含 capacity
个示例,并且只有在它到达后才需要获取新数据min_after_dequeue
低于 capacity
,这会导致 GPU 利用率稳定。
但实际上,一旦队列达到 min_after_dequeue
个示例,训练就会开始。因此,一旦队列达到 min_after_dequeue
示例到 运行 train_op
,队列就会被出列,并且由于填充队列的时间比 [= 的执行时间慢 15 倍11=],队列中的元素数量在 train_op
的第一次迭代后立即下降到 min_after_dequeue
以下,并且 train_op
必须等待队列再次到达 min_after_dequeue
例子。
当我强制 train_op
等到队列达到 capacity
(使用 capacity = 100*batch
)而不是在到达 min_after_dequeue
时自动启动(使用min_after_dequeue=80*batch
),GPU 利用率在回到 0% 之前稳定了大约 10 秒,这是可以理解的,因为队列在不到 10 秒的时间内达到 min_after_dequeue
示例。
我将 tensorflow 与 Titan-X GPU 一起使用,我注意到,当我 运行 CIFAR10 示例时,Volatile GPU-utilization
非常稳定地保持在 30% 左右,而当我训练时在我自己的模型中,Volatile GPU-utilization
远非稳定,它几乎总是 0%,在回到 0% 之前达到 80/90%,一遍又一遍。
我认为这种行为是由于我将数据馈送到网络的方式造成的(我在每一步之后获取数据,这需要一些时间)。但是在实现队列来提供数据并避免步骤之间的这种延迟之后,问题仍然存在(请参阅下面的队列系统)。
有什么想法吗?
batch = 128 # size of the batch
x = tf.placeholder("float32", [None, n_steps, n_input])
y = tf.placeholder("float32", [None, n_classes])
# with a capacity of 100 batches, the bottleneck should not be the data feeding
queue = tf.RandomShuffleQueue(capacity=100*batch,
min_after_dequeue=80*batch,
dtypes=[tf.float32, tf.float32],
shapes=[[n_steps, n_input], [n_classes]])
enqueue_op = queue.enqueue_many([x, y])
X_batch, Y_batch = queue.dequeue_many(batch)
sess = tf.Session()
def load_and_enqueue(data):
while True:
X, Y = data.get_next_batch(batch)
sess.run(enqueue_op, feed_dict={x: X, y: Y})
train_thread = threading.Thread(target=load_and_enqueue, args=(data))
train_thread.daemon = True
train_thread.start()
for _ in xrange(max_iter):
sess.run(train_op)
在做了一些实验之后,我找到了答案,所以我 post 因为它可能对其他人有用。
首先,get_next_batch
比 train_op
慢大约 15 倍(感谢 Eric Platon 指出这一点)。
但是,我认为队列正在被填充到 capacity
,并且只有在训练应该开始之后。因此,我认为即使 get_next_batch
慢得多,队列也应该隐藏这种延迟,至少在开始时,因为它包含 capacity
个示例,并且只有在它到达后才需要获取新数据min_after_dequeue
低于 capacity
,这会导致 GPU 利用率稳定。
但实际上,一旦队列达到 min_after_dequeue
个示例,训练就会开始。因此,一旦队列达到 min_after_dequeue
示例到 运行 train_op
,队列就会被出列,并且由于填充队列的时间比 [= 的执行时间慢 15 倍11=],队列中的元素数量在 train_op
的第一次迭代后立即下降到 min_after_dequeue
以下,并且 train_op
必须等待队列再次到达 min_after_dequeue
例子。
当我强制 train_op
等到队列达到 capacity
(使用 capacity = 100*batch
)而不是在到达 min_after_dequeue
时自动启动(使用min_after_dequeue=80*batch
),GPU 利用率在回到 0% 之前稳定了大约 10 秒,这是可以理解的,因为队列在不到 10 秒的时间内达到 min_after_dequeue
示例。