AMD plaidml与CPU Tensorflow-意外结果

时间:2019-09-29 15:19:08

标签: python python-3.x tensorflow machine-learning keras

我目前正在运行一个简单的脚本来训练mnist数据集。

通过Tensorflow在我的CPU上运行训练,使用以下代码给了我49us/sample和3e纪元:-

# CPU

import tensorflow as tf
mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = tf.keras.utils.normalize(x_train, axis=1)
x_test = tf.keras.utils.normalize(x_test, axis=1)

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(128, activation=tf.nn.relu))
model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))

model.compile(optimizer='adam', loss="sparse_categorical_crossentropy", metrics=["accuracy"])

model.fit(x_train, y_train, epochs=3)

当我使用opencl_amd_radeon_pro_580_compute_engine通过pladml设置通过AMD Pro 580运行数据集时,使用以下代码以15秒的时间获得了以下结果249us/sample:-

# GPU

import plaidml.keras
plaidml.keras.install_backend()
import keras
from keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = keras.utils.normalize(x_train, axis=1)
x_test = keras.utils.normalize(x_test, axis=1)

model = keras.models.Sequential()
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(128, activation='relu'))
model.add(keras.layers.Dense(128, activation='relu'))
model.add(keras.layers.Dense(10, activation='softmax'))

model.compile(optimizer='adam', loss="sparse_categorical_crossentropy", metrics=["accuracy"])

model.fit(x_train, y_train, epochs=3)

我可以看到我的CPU为进行CPU测试而启动,而GPU为GPU测试而达到最大值,但是对于为什么CPU不能以5倍的速度执行GPU感到非常困惑。

这应该是预期的结果吗?

我在代码中做错了吗?

2 个答案:

答案 0 :(得分:7)

看来我至少在macOS / Keras / AMD GPU设置上找到了正确的解决方案。

TL; DR:

  • 不要不要使用OpenCL,而应使用*metal
  • 使用Tensorflow 2.0,仅使用Keras API

以下是详细信息:

运行plaidml-setup并拾取金属??这很重要!

...
Multiple devices detected (You can override by setting PLAIDML_DEVICE_IDS).
Please choose a default device:

   1 : llvm_cpu.0
   2 : metal_intel(r)_uhd_graphics_630.0
   3 : metal_amd_radeon_pro_560x.0

Default device? (1,2,3)[1]:3
...

确保已保存更改:

Save settings to /Users/alexanderegorov/.plaidml? (y,n)[y]:y
Success!

现在运行MNIST示例,您应该看到类似以下内容的

INFO:plaidml:Opening device "metal_amd_radeon_pro_560x.0"

就是这样。我使用plaidbench keras mobilenet作了比较:

metal_amd_radeon_pro_560x.0 最快!

  • 示例完成,经过:0.435s(编译),8.057s(执行)

opencl_amd_amd_radeon_pro_560x_compute_engine.0

  • 示例完成,经过:3.197s(编译),14.620s(执行)

llvm_cpu.0

  • 示例完成,经过:3.619s(编译),47.837s(执行)

答案 1 :(得分:1)

我认为观察到的情况有两个方面:

  1. plaidml在我的经历中并不出色,可悲的是,我得到了类似的结果。
  2. 将数据移至GPU的速度很慢。在这种情况下,MNIST数据确实很小,将数据移到那里的时间超过了并行计算的“好处”。实际上,TF CPU可能也执行并行矩阵乘法,但是由于数据较小且更靠近处理单元,因此速度要快得多。