I have a MacBook Pro with AMD processor and I want to run Keras (Tensorflow backend) in this GPU. I came to know Keras only works with NVIDIA GPUs. What is the workaround (if possible)?
2 Answers
You can OpenCL library to overcome this. I have tested it and it is working fine for me.
Note: I have python version 3.7 and I will be using pip3 for package installation.
Steps:
Install OpenCL package with the following command
pip3 install pyopencl
Install PlaidML library using following command
pip3 install pip install plaidml-keras
Run setup for PlaidML. While setup you might get a prompt to select your GPU. If setup went correctly, you will get a success message at the end.
plaidml-setup
Install plaidbench to test plaidml on your GPU.
pip3 install plaidbench
Test it. If everything went well till here you will get benchmark scores.
plaidbench keras mobilenet
Now we have to set an environment path. Put this at the top of your code.
import os
os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
os.environ["RUNFILES_DIR"] = "/Library/Frameworks/Python.framework/Versions/3.7/share/plaidml"
# plaidml might exist in different location. Look for "/usr/local/share/plaidml" and replace in above path
os.environ["PLAIDML_NATIVE_PATH"] = "/Library/Frameworks/Python.framework/Versions/3.7/lib/libplaidml.dylib"
# libplaidml.dylib might exist in different location. Look for "/usr/local/lib/libplaidml.dylib" and replace in above path
- Test in actual code. Use
keras
instead oftensorflow.keras
in your code and run the following. (keras is installed in step 2 which runs in GPU)
import os
# IMPORTANT: PATH MIGHT BE DIFFERENT. SEE STEP 6
os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
os.environ["RUNFILES_DIR"] = "/Library/Frameworks/Python.framework/Versions/3.7/share/plaidml"
os.environ["PLAIDML_NATIVE_PATH"] = "/Library/Frameworks/Python.framework/Versions/3.7/lib/libplaidml.dylib"
# Don't use tensorflow.keras anywhere, instead use keras
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
batch_size = 128
num_classes = 10
epochs = 12
# input image dimensions
img_rows, img_cols = 28, 28
# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
if K.image_data_format() == 'channels_first':
x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
activation='relu',
input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,
optimizer=keras.optimizers.Adadelta(),
metrics=['accuracy'])
model.fit(x_train, y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_data=(x_test, y_test))
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
When you run this you will get
Using plaidml.keras.backend backend.
INFO:plaidml:Opening device "metal_intel(r)_iris(tm)_graphics_6100.0"
# or whatever GPU you selected in step 3
which confirms that you are running it in GPU.
Reference: https://towardsdatascience.com/gpu-accelerated-machine-learning-on-macos-48d53ef1b545

- 7,127
- 2
- 51
- 63
-
1@bikram, thanks for your answer! I have the same conclusion after all own experiments. So you can't use TF2.0 with macOS+AMD GPU. I'm not sure this is bad or limiting somehow. Basically TF2.0 is moving towards easiness and simplicity of Keras APIFurthermore it is not so hard to adopt TF2.0 code to use only Keras API. – sashaegorov Apr 19 '20 at 13:31
-
@sashaegorov Exactly. – bikram Jun 29 '20 at 08:55
-
2PlaidML can run on MacBook using Metal (which performs better than OpenCL, at least in my case), so step 1 is optional. Also step 6 works without setting paths for RUNFILES_DIR and PLAIDML_NATIVE_PATH, and the only required environment variable is KERAS_BACKEND – fdermishin Oct 17 '20 at 16:38
-
How long does it take to run this code? I see that my code is running on gpu but each epoch took about 79 seconds – ozgur Jan 28 '21 at 16:32
-
PlaidML doesn't seem to be 1-1 with Tensorflow.keras. Does that sound right? I have existing code/model that uses Huber loss function as an example. But that class - tf.keras.losses.Huber - doesn't exist in PlaidML. So the code requires porting. Is this your understanding as well, that the use of GPU here means it's not 1-1 in functionality? – Heems Jun 15 '21 at 05:41
In fact it is not true that Keras supports only NVIDIA GPUs. You can choose, which backend Keras is using, and if this backend supports AMD GPUs, then Keras should work in that case too.
However the only backend that works on MacOS is PlaidML. There is also ROCm for AMD processors, but it is not supported on MacOS as of Oct 2020 (see this discussion).

- 3,519
- 3
- 24
- 45