为什么要从源代码构建Tensorflow?

Tensorflow是谷歌广受欢迎的机器学习库。它于2015年推出,截至撰写本文时,它是世界上最受欢迎的机器学习库。使用pip安装Tensorflow非常简单直接。但是,tensorflow的官方最佳实践指南说,如果使用CPU,最好从源代码构建Tensorflow。这是为什么?这是因为从源代码构建时,您可以编译Tensorflow以使用可用于特定CPU的所有优化。这会产生重大影响。

首先,要从源代码构建,您需要安装Bazel,然后克隆Tensorflow github存储库。详细说明可在此处找到(https://www.tensorflow.org/install/install_sources)。完成后,您需要确定选项,以便优化CPU的构建。这可以通过两种方式完成:

  • 谷歌。找出您正在使用的CPU以及可用于CPU的所有优化。
  • 使用这个脚本(https://gist.github.com/venik/9ba962c8b301b0e21f99884cbd35082f),适用于MacOS和Linux。它可以自动计算出您的CPU和平台,并使用所有正确的标志运行Bazel构建。

问题是它真的加快了性能吗?

首先,让我们进行基本矩阵乘法以查看加速。Python实现如下:

import tensorflow as tf

import time

m1 = []

m2 = []

result = []

i = 10

while i <= 10000:

m1.append(tf.random_uniform(shape = [i, i]))

m2.append(tf.random_uniform(shape = [i, i]))

i *= 10

for t1, t2 in zip(m1, m2):

result.append(tf.matmul(t1, t2))

sess = tf.Session()

for tensor in result:

start = time.time()

sess.run(tensor)

print(tensor.shape, time.time() - start)

结果如下:

为什么要从源代码构建Tensorflow?

速度从22%上升到52%,这看起来很有希望,接下来我们尝试使用神经网络。

我写了一个简单的前馈全连接神经网络分类器并使用了MNIST数据集。代码从命令行中获取了一个参数:隐藏层的数量。所以我将测试从3个隐藏层运行到10个隐藏层,每个层有1000个节点。Python代码如下:

from tensorflow.examples.tutorials.mnist import input_data

import sys

layers = int(sys.argv[1])

import tensorflow as tf

from time import time

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

x = tf.placeholder(tf.float32, [None, 784])

hiddenLayer = tf.layers.dense(x, 1000, activation = tf.nn.tanh)

lastLayer = hiddenLayer

for i in range(layers):

lastLayer = tf.layers.dense(lastLayer, 1000, activation = tf.nn.tanh)

output = tf.layers.dense(lastLayer, 10)

y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_, logits = output)

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

sess = tf.Session()

sess.run(tf.global_variables_initializer())

then = time()

for _ in range(550):

print(_, end = "")

batch_xs, batch_ys = mnist.train.next_batch(100)

sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

print(layers, time() - then)

结果如下:

为什么要从源代码构建Tensorflow?

为什么要从源代码构建Tensorflow?

正如我们所看到的,增长速度是28-43%。那么卷积神经网络(CNN)呢?

我写了一个简单的CNN网络来分类相同的MNIST数据集。网络有n个卷积层,然后是最大池化层,然后是一个的全连接隐藏层。Python代码如下:

import tensorflow as tf

tf.logging.set_verbosity(tf.logging.ERROR)

from tensorflow.examples.tutorials.mnist import input_data

from time import time

import sys

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

image_size = 28

x = tf.placeholder(tf.float32, [None, 784])

input2d = tf.reshape(x, [-1, image_size, image_size, 1])

layers = int(sys.argv[1])

conv1 = tf.layers.conv2d(inputs=input2d, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)

conv = conv1

for i in range(layers):

conv = tf.layers.conv2d(inputs=conv, filters=32, kernel_size=[5, 5], padding="same", activation=tf.nn.relu)

pool1 = tf.layers.max_pooling2d(inputs=conv, pool_size=[2, 2], strides=2)

pool_flat = tf.layers.flatten(pool1)

hidden = tf.layers.dense(inputs= pool_flat, units=1024, activation=tf.nn.relu)

output = tf.layers.dense(inputs=hidden, units=10)

y_ = tf.placeholder(tf.float32, [None, 10])

cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(labels = y_, logits = output)

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

sess = tf.Session()

sess.run(tf.global_variables_initializer())

then = time()

for _ in range(550):

print(_, end = "")

batch_xs, batch_ys = mnist.train.next_batch(100)

sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

print(layers, time() - then)

结果如下:

为什么要从源代码构建Tensorflow?

为什么要从源代码构建Tensorflow?

加速只有18-26%,为什么呢?为什么加速降低?这是因为当你从源码构建时,最大的加速是在矩阵乘法中,因为tensorflow使用Eigen进行矩阵乘法使用CPU,这是相当优化的。前馈神经网络主要由矩阵乘法组成,其中CNN大部分时间都在卷积中。

相关推荐