在 keras.utils.multi_gpu_model 下使用多 GPU 时 SageMaker 失败
SageMaker fails when using Multi-GPU with keras.utils.multi_gpu_model
运行 带有自定义模型的 AWS SageMaker,在多 gpu 配置中使用 Keras 和 Tensorflow 后端时,TrainingJob 失败并出现算法错误:
from keras.utils import multi_gpu_model
parallel_model = multi_gpu_model(model, gpus=K)
parallel_model.compile(loss='categorical_crossentropy',
optimizer='rmsprop')
parallel_model.fit(x, y, epochs=20, batch_size=256)
这个简单的并行模型加载将失败。 CloudWatch 日志记录没有进一步的错误或异常。此配置在具有 2x NVIDIA GTX 1080、相同 Keras Tensorflow 后端的本地计算机上正常工作。
根据 SageMaker 文档和 tutorials,当 Keras 后端是 MXNet 时,multi_gpu_model
实用程序可以正常工作,但当后端是具有相同多 GPU 配置的 Tensorflow 时,我没有发现任何提及。
[更新]
我已经使用下面的建议答案更新了代码,并且在 TrainingJob 挂起之前添加了一些日志记录
此记录重复两次
2018-11-27 10:02:49.878414: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0, 1, 2, 3
2018-11-27 10:02:49.878462: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-11-27 10:02:49.878471: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988] 0 1 2 3
2018-11-27 10:02:49.878477: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0: N Y Y Y
2018-11-27 10:02:49.878481: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 1: Y N Y Y
2018-11-27 10:02:49.878486: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 2: Y Y N Y
2018-11-27 10:02:49.878492: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 3: Y Y Y N
2018-11-27 10:02:49.879340: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:0 with 14874 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1b.0, compute capability: 7.0)
2018-11-27 10:02:49.879486: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:1 with 14874 MB memory) -> physical GPU (device: 1, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1c.0, compute capability: 7.0)
2018-11-27 10:02:49.879694: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:2 with 14874 MB memory) -> physical GPU (device: 2, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1d.0, compute capability: 7.0)
2018-11-27 10:02:49.879872: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:3 with 14874 MB memory) -> physical GPU (device: 3, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1e.0, compute capability: 7.0)
在每个 GPU 的一些日志信息之前,重复 4 次
2018-11-27 10:02:46.447639: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 3 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:1e.0
totalMemory: 15.78GiB freeMemory: 15.37GiB
根据日志记录,所有 4 个 GPU 都可见并已加载到 Tensorflow Keras 后端。之后没有应用程序日志记录,TrainingJob 状态暂时为 inProgress,之后变为 Failed,使用相同的 Algorithm错误.
查看 CloudWatch 日志记录,我可以看到一些指标在起作用。具体来说 GPU Memory Utilization
, CPU Utilization
是可以的,而 GPU utilization
是 0%.
[更新]
由于 Keras 上的一个 known 错误是关于保存多 GPU 模型,我正在使用 multi_gpu_model 实用程序keras.utils
from keras.layers import Lambda, concatenate
from keras import Model
import tensorflow as tf
def multi_gpu_model(model, gpus):
#source: https://github.com/keras-team/keras/issues/8123#issuecomment-354857044
if isinstance(gpus, (list, tuple)):
num_gpus = len(gpus)
target_gpu_ids = gpus
else:
num_gpus = gpus
target_gpu_ids = range(num_gpus)
def get_slice(data, i, parts):
shape = tf.shape(data)
batch_size = shape[:1]
input_shape = shape[1:]
step = batch_size // parts
if i == num_gpus - 1:
size = batch_size - step * i
else:
size = step
size = tf.concat([size, input_shape], axis=0)
stride = tf.concat([step, input_shape * 0], axis=0)
start = stride * i
return tf.slice(data, start, size)
all_outputs = []
for i in range(len(model.outputs)):
all_outputs.append([])
# Place a copy of the model on each GPU,
# each getting a slice of the inputs.
for i, gpu_id in enumerate(target_gpu_ids):
with tf.device('/gpu:%d' % gpu_id):
with tf.name_scope('replica_%d' % gpu_id):
inputs = []
# Retrieve a slice of the input.
for x in model.inputs:
input_shape = tuple(x.get_shape().as_list())[1:]
slice_i = Lambda(get_slice,
output_shape=input_shape,
arguments={'i': i,
'parts': num_gpus})(x)
inputs.append(slice_i)
# Apply model on slice
# (creating a model replica on the target device).
outputs = model(inputs)
if not isinstance(outputs, list):
outputs = [outputs]
# Save the outputs for merging back together later.
for o in range(len(outputs)):
all_outputs[o].append(outputs[o])
# Merge outputs on CPU.
with tf.device('/cpu:0'):
merged = []
for name, outputs in zip(model.output_names, all_outputs):
merged.append(concatenate(outputs,
axis=0, name=name))
return Model(model.inputs, merged)
这在本地 2x NVIDIA GTX 1080 / Intel Xeon / Ubuntu 16.04
上工作正常。它会在 SageMaker 训练作业上失败。
我已在
的 AWS Sagemaker 论坛上发布了这个问题
[更新]
我稍微修改了 tf.session
代码,添加了一些初始化程序
with tf.Session() as session:
K.set_session(session)
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
现在至少我可以从实例指标中看到使用了一个 GPU(我假设设备 gpu:0
)。无论如何,多GPU都不工作。
这可能不是您问题的最佳答案,但这是我用于带有 Tensorflow 后端的多 GPU 模型的答案。首先我初始化使用:
def setup_multi_gpus():
"""
Setup multi GPU usage
Example usage:
model = Sequential()
...
multi_model = multi_gpu_model(model, gpus=num_gpu)
multi_model.fit()
About memory usage:
"""
import tensorflow as tf
from keras.utils.training_utils import multi_gpu_model
from tensorflow.python.client import device_lib
# IMPORTANT: Tells tf to not occupy a specific amount of memory
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU
sess = tf.Session(config=config)
set_session(sess) # set this TensorFlow session as the default session for Keras.
# getting the number of GPUs
def get_available_gpus():
local_device_protos = device_lib.list_local_devices()
return [x.name for x in local_device_protos if x.device_type == 'GPU']
num_gpu = len(get_available_gpus())
print('Amount of GPUs available: %s' % num_gpu)
return num_gpu
那我打电话给
# Setup multi GPU usage
num_gpu = setup_multi_gpus()
并创建一个模型。
...
之后您可以将其设为多 GPU 模型。
multi_model = multi_gpu_model(model, gpus=num_gpu)
multi_model.compile...
multi_model.fit...
此处与您所做的唯一不同的是 Tensorflow 初始化 GPU 的方式。我无法想象这是问题所在,但可能值得一试。
祝你好运!
编辑:我注意到序列到序列无法使用多 GPU。这是您要训练的模型类型吗?
对于回复缓慢,我深表歉意。
好像有很多线程是运行并发的,想把它们link放在一起,让有同样问题的其他人看到进度和讨论进行中。
https://forums.aws.amazon.com/thread.jspa?messageID=881541
https://forums.aws.amazon.com/thread.jspa?messageID=881540
https://github.com/aws/sagemaker-python-sdk/issues/512
关于这个有几个问题。
什么版本的 TensorFlow 和 Keras?
我不太确定是什么导致了这个问题。您的容器是否具有所有需要的依赖项,例如 CUDA 等? https://www.tensorflow.org/install/gpu
你能用 Keras 使用单个 GPU 进行训练吗?
运行 带有自定义模型的 AWS SageMaker,在多 gpu 配置中使用 Keras 和 Tensorflow 后端时,TrainingJob 失败并出现算法错误:
from keras.utils import multi_gpu_model
parallel_model = multi_gpu_model(model, gpus=K)
parallel_model.compile(loss='categorical_crossentropy',
optimizer='rmsprop')
parallel_model.fit(x, y, epochs=20, batch_size=256)
这个简单的并行模型加载将失败。 CloudWatch 日志记录没有进一步的错误或异常。此配置在具有 2x NVIDIA GTX 1080、相同 Keras Tensorflow 后端的本地计算机上正常工作。
根据 SageMaker 文档和 tutorials,当 Keras 后端是 MXNet 时,multi_gpu_model
实用程序可以正常工作,但当后端是具有相同多 GPU 配置的 Tensorflow 时,我没有发现任何提及。
[更新]
我已经使用下面的建议答案更新了代码,并且在 TrainingJob 挂起之前添加了一些日志记录
此记录重复两次
2018-11-27 10:02:49.878414: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1511] Adding visible gpu devices: 0, 1, 2, 3
2018-11-27 10:02:49.878462: I tensorflow/core/common_runtime/gpu/gpu_device.cc:982] Device interconnect StreamExecutor with strength 1 edge matrix:
2018-11-27 10:02:49.878471: I tensorflow/core/common_runtime/gpu/gpu_device.cc:988] 0 1 2 3
2018-11-27 10:02:49.878477: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 0: N Y Y Y
2018-11-27 10:02:49.878481: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 1: Y N Y Y
2018-11-27 10:02:49.878486: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 2: Y Y N Y
2018-11-27 10:02:49.878492: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1001] 3: Y Y Y N
2018-11-27 10:02:49.879340: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:0 with 14874 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1b.0, compute capability: 7.0)
2018-11-27 10:02:49.879486: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:1 with 14874 MB memory) -> physical GPU (device: 1, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1c.0, compute capability: 7.0)
2018-11-27 10:02:49.879694: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:2 with 14874 MB memory) -> physical GPU (device: 2, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1d.0, compute capability: 7.0)
2018-11-27 10:02:49.879872: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/device:GPU:3 with 14874 MB memory) -> physical GPU (device: 3, name: Tesla V100-SXM2-16GB, pci bus id: 0000:00:1e.0, compute capability: 7.0)
在每个 GPU 的一些日志信息之前,重复 4 次
2018-11-27 10:02:46.447639: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 3 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0000:00:1e.0
totalMemory: 15.78GiB freeMemory: 15.37GiB
根据日志记录,所有 4 个 GPU 都可见并已加载到 Tensorflow Keras 后端。之后没有应用程序日志记录,TrainingJob 状态暂时为 inProgress,之后变为 Failed,使用相同的 Algorithm错误.
查看 CloudWatch 日志记录,我可以看到一些指标在起作用。具体来说 GPU Memory Utilization
, CPU Utilization
是可以的,而 GPU utilization
是 0%.
[更新]
由于 Keras 上的一个 known 错误是关于保存多 GPU 模型,我正在使用 multi_gpu_model 实用程序keras.utils
from keras.layers import Lambda, concatenate
from keras import Model
import tensorflow as tf
def multi_gpu_model(model, gpus):
#source: https://github.com/keras-team/keras/issues/8123#issuecomment-354857044
if isinstance(gpus, (list, tuple)):
num_gpus = len(gpus)
target_gpu_ids = gpus
else:
num_gpus = gpus
target_gpu_ids = range(num_gpus)
def get_slice(data, i, parts):
shape = tf.shape(data)
batch_size = shape[:1]
input_shape = shape[1:]
step = batch_size // parts
if i == num_gpus - 1:
size = batch_size - step * i
else:
size = step
size = tf.concat([size, input_shape], axis=0)
stride = tf.concat([step, input_shape * 0], axis=0)
start = stride * i
return tf.slice(data, start, size)
all_outputs = []
for i in range(len(model.outputs)):
all_outputs.append([])
# Place a copy of the model on each GPU,
# each getting a slice of the inputs.
for i, gpu_id in enumerate(target_gpu_ids):
with tf.device('/gpu:%d' % gpu_id):
with tf.name_scope('replica_%d' % gpu_id):
inputs = []
# Retrieve a slice of the input.
for x in model.inputs:
input_shape = tuple(x.get_shape().as_list())[1:]
slice_i = Lambda(get_slice,
output_shape=input_shape,
arguments={'i': i,
'parts': num_gpus})(x)
inputs.append(slice_i)
# Apply model on slice
# (creating a model replica on the target device).
outputs = model(inputs)
if not isinstance(outputs, list):
outputs = [outputs]
# Save the outputs for merging back together later.
for o in range(len(outputs)):
all_outputs[o].append(outputs[o])
# Merge outputs on CPU.
with tf.device('/cpu:0'):
merged = []
for name, outputs in zip(model.output_names, all_outputs):
merged.append(concatenate(outputs,
axis=0, name=name))
return Model(model.inputs, merged)
这在本地 2x NVIDIA GTX 1080 / Intel Xeon / Ubuntu 16.04
上工作正常。它会在 SageMaker 训练作业上失败。
我已在
的 AWS Sagemaker 论坛上发布了这个问题[更新]
我稍微修改了 tf.session
代码,添加了一些初始化程序
with tf.Session() as session:
K.set_session(session)
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
现在至少我可以从实例指标中看到使用了一个 GPU(我假设设备 gpu:0
)。无论如何,多GPU都不工作。
这可能不是您问题的最佳答案,但这是我用于带有 Tensorflow 后端的多 GPU 模型的答案。首先我初始化使用:
def setup_multi_gpus():
"""
Setup multi GPU usage
Example usage:
model = Sequential()
...
multi_model = multi_gpu_model(model, gpus=num_gpu)
multi_model.fit()
About memory usage:
"""
import tensorflow as tf
from keras.utils.training_utils import multi_gpu_model
from tensorflow.python.client import device_lib
# IMPORTANT: Tells tf to not occupy a specific amount of memory
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.allow_growth = True # dynamically grow the memory used on the GPU
sess = tf.Session(config=config)
set_session(sess) # set this TensorFlow session as the default session for Keras.
# getting the number of GPUs
def get_available_gpus():
local_device_protos = device_lib.list_local_devices()
return [x.name for x in local_device_protos if x.device_type == 'GPU']
num_gpu = len(get_available_gpus())
print('Amount of GPUs available: %s' % num_gpu)
return num_gpu
那我打电话给
# Setup multi GPU usage
num_gpu = setup_multi_gpus()
并创建一个模型。
...
之后您可以将其设为多 GPU 模型。
multi_model = multi_gpu_model(model, gpus=num_gpu)
multi_model.compile...
multi_model.fit...
此处与您所做的唯一不同的是 Tensorflow 初始化 GPU 的方式。我无法想象这是问题所在,但可能值得一试。
祝你好运!
编辑:我注意到序列到序列无法使用多 GPU。这是您要训练的模型类型吗?
对于回复缓慢,我深表歉意。
好像有很多线程是运行并发的,想把它们link放在一起,让有同样问题的其他人看到进度和讨论进行中。
https://forums.aws.amazon.com/thread.jspa?messageID=881541 https://forums.aws.amazon.com/thread.jspa?messageID=881540
https://github.com/aws/sagemaker-python-sdk/issues/512
关于这个有几个问题。
什么版本的 TensorFlow 和 Keras?
我不太确定是什么导致了这个问题。您的容器是否具有所有需要的依赖项,例如 CUDA 等? https://www.tensorflow.org/install/gpu
你能用 Keras 使用单个 GPU 进行训练吗?