Tensorflow与Numpy性能比较

3
我正在使用numpy计算平均值和标准差。为了提高性能,我尝试使用Tensorflow进行相同的操作,但是Tensorflow至少慢了约10倍。我在Tensorflow中尝试了两种方法(如下所示)。第一种方法使用tf.nn.moments(),它有一个错误会导致方差有时返回负值。在第二种方法中,我通过其他Tensorflow函数计算方差。
我尝试过CPU和GPU;numpy始终更快。
我使用time.time()而不是time.clock()来测量使用GPU时的墙钟时间。
为什么Tensorflow更慢?我认为这可能是由于将数据传输到GPU,但即使对于非常小的数据集(传输时间应该可以忽略不计),并且仅使用CPU时,TF也较慢。这是由于初始化TF所需的开销时间吗?
import tensorflow as tf
import numpy
import time
import math

class Timer:
    def __enter__(self):
        self.start = time.time()
        return self

    def __exit__(self, *args):
        self.end = time.time()
        self.interval = self.end - self.start

inData = numpy.random.uniform(low=-1, high=1, size=(40000000,))

with Timer() as t:
    mean = numpy.mean(inData)
print 'python mean', mean, 'time', t.interval

with Timer() as t:
    stdev = numpy.std(inData)
print 'python stdev', stdev, 'time', t.interval

# Approach 1 (Note tf.nn.moments() has a bug)
with Timer() as t:
    with tf.Graph().as_default():
        meanTF, varianceTF = tf.nn.moments(tf.constant(inData), axes=[0])
        init_op = tf.global_variables_initializer()
        with tf.Session() as sess:
            sess.run(init_op)
            mean, variance = sess.run([meanTF, varianceTF])
            sess.close()
print 'variance', variance
stdev = math.sqrt(variance)
print 'tensorflow mean', mean, 'stdev', stdev, 'time', t.interval

# Approach 2
with Timer() as t:
    with tf.Graph().as_default():
        inputVector = tf.constant(inData)
        meanTF = tf.reduce_mean(inputVector)
        length = tf.size(inputVector)
        varianceTF = tf.divide(tf.reduce_sum(tf.squared_difference(inputVector, mean)), tf.to_double(length))
        init_op = tf.global_variables_initializer()
        with tf.Session() as sess:
            sess.run(init_op)
            mean, variance = sess.run([meanTF, varianceTF])
            sess.close()
print 'variance', variance
stdev = math.sqrt(variance)
print 'tensorflow mean', mean, 'stdev', stdev, 'time', t.interval

我认为可能是因为将数据传输到GPU,但即使对于非常小的数据集,TF也比较慢。这看起来像你交换了一些东西。我会说你的计算方式很简单,所以numpy由于使用专门的函数和BLAS的使用达到了极限(取决于您的BLAS设置;例如,在Ubuntu中默认设置)。Tensorflow不能做太多魔术来变得更好(同时保证相同的准确性)。 - sascha
Tensorflow在我的测试中一直比Numpy慢得多。既然Tensorflow使用GPU而Numpy仅使用CPU,那么Tensorflow不应该更快吗?我正在运行Ubuntu,并且没有更改任何影响BLAS的内容(据我所知)。 - Ron Cohen
1
这总是取决于任务。有些算法可以很好地并行处理,而有些则不行(您已经提到了其他参数,如传输,还有数据类型和协同处理)。并非所有工作都适合GPU。 - sascha
3个回答

4
以下是稍微更好的基准测试。在Xeon V3上进行测试,使用所有优化选项+来自此处的XLA编译的仅CPU版本的TensorFlow与最新anaconda附带的numpy MKL进行比较。
可能在这里XLA没有起到作用,但为了记录而保留它。
注意事项:
  1. 从计时中排除前几次运行,它们可能包括初始化/分析。
  2. 使用变量以避免将输入复制到Tensorflow运行时中。
  3. 在调用之间扰动变量,以确保没有缓存。
结果:
   numpy 23.5 ms, 25.7 ms
      tf 14.7 ms, 20.5 ms

代码:

import numpy as np
import tensorflow as tf
import time
from tensorflow.contrib.compiler import jit
jit_scope = jit.experimental_jit_scope

inData = np.random.uniform(low=-1, high=1, size=(40000000,)).astype(np.float32)
#inDataFeed = tf.placeholder(inData.dtype)

with jit_scope(compile_ops=True):
    inDataVar = tf.Variable(inData)
    meanTF = tf.reduce_mean(inDataVar)


sess = tf.Session()
times = []
sess.run(tf.global_variables_initializer())
num_tries = 10


times = []
for i in range(num_tries):
    t0 = time.perf_counter()
    mean = np.mean(inData)
    times.append(time.perf_counter()-t0)

print("%10s %.1f ms, %.1f ms" %("numpy", 10**3*min(times),
                                10**3*np.median(times)))

times = []
perturb = inDataVar.assign_add(tf.random_uniform(inData.shape))
for i in range(num_tries):
    sess.run(perturb)
    t0 = time.perf_counter()
    mean, = sess.run([meanTF])
    times.append(time.perf_counter()-t0)

times = times[2:] # discard first few because they could include profiling runs
print("%10s %.1f ms, %.1f ms" %("tf", 10**3*min(times),
                                10**3*np.median(times)))

谢谢Yaroslav。我的原始目标是通过GPU来提升性能。您知道在将数据加载到GPU并开始GPU会话时是否会有显著的开销时间吗? - Ron Cohen
是的,启动GPU会话是非常重要的开销,在某些不幸的情况下可能需要超过30秒(例如当您使用未编译计算能力的视频卡时,如GTX 1080)。 - Yaroslav Bulatov

2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接