使用自定义模型运行AWS SageMaker,在多GPU配置中使用Keras加上Tensorflow后端时,TrainingJob失败,并出现 Algorithm Error (算法错误)。
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日志记录没有其他错误或异常。此配置在具有2个NVIDIA GTX 1080和相同Keras Tensorflow后端的本地计算机上可以正常工作。
根据SageMaker文档和tutorials,multi_gpu_model
实用程序在Keras后端为MXNet时可以正常使用,但是当后端为具有相同多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 ,此后变为失败,并带有相同的算法错误。>
查看CloudWatch日志记录,我可以看到一些工作指标。具体来说,GPU Memory Utilization
,CPU Utilization
可以,而GPU utilization
为0%。
[更新]
由于Keras上的一个known错误,该错误与保存多GPU模型有关,因此我在 keras.utils multi_gpu_model 实用程序的此替代。 >
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论坛上发布了此问题TrainingJob custom algorithm with Keras backend and multi GPU
SageMaker Fails when using Multi-GPU with keras.utils.multi_gpu_model
[更新]
我对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仍然无法正常工作。
答案 0 :(得分:2)
这可能不是您所遇到问题的最佳答案,但这就是我正在使用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:
https://stackoverflow.com/questions/34199233/how-to-prevent-tensorflow-from-allocating-the-totality-of-a-gpu-memory
"""
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一起使用。这是您要训练的模型类型吗?
答案 1 :(得分:1)
很抱歉我的反应慢。
似乎有许多并行运行的线程,我想将它们链接在一起,以便其他有相同问题的人可以看到进度和讨论。
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进行训练?