Amazon SageMaker批量转换GPU利用率为零问题求助
我把本地GPU训练的Keras(TensorFlow后端)图像分类模型部署到AWS SageMaker,用Batch Transform做批量预测时,任务能成功运行,但CloudWatch显示GPU利用率始终为0,可GPU显存利用率却到了97%,处理500张图片花了7分钟,比本地GPU慢太多了。更奇怪的是,同一模型部署到实时端点时,GPU是能正常使用的。
模型准备步骤
我按照AWS指南把Keras模型转成了SageMaker兼容的格式,代码如下:
import tensorflow as tf from tensorflow.python.saved_model import builder from tensorflow.python.saved_model.signature_def_utils import predict_signature_def from tensorflow.python.saved_model import tag_constants import tarfile import sagemaker # 禁用即时执行模式 if tf.executing_eagerly(): tf.compat.v1.disable_eager_execution() builder = builder.SavedModelBuilder(export_dir) # 创建供TensorFlow Serving Predict API使用的预测签名 signature = predict_signature_def( inputs={"image_bytes": model.input}, outputs={"score_bytes": model.output}) with tf.compat.v1.keras.backend.get_session() as sess: # 保存元图和变量 builder.add_meta_graph_and_variables( sess=sess, tags=[tag_constants.SERVING], signature_def_map={"serving_default": signature}) builder.save() with tarfile.open(tar_model_file, mode='w:gz') as archive: archive.add('export', recursive=True) sagemaker_session = sagemaker.Session() s3_uri = sagemaker_session.upload_data(path=tar_model_file, bucket=bucket, key_prefix=sagemaker_model_dir)
批量转换配置
我用的是GPU推理镜像:763104351884.dkr.ecr.eu-central-1.amazonaws.com/tensorflow-inference:2.0.0-gpu,相关配置代码:
framework = 'tensorflow' instance_type='ml.p3.2xlarge' image_scope = 'inference' tf_version = '2.0.0' py_version = '3.6' sagemaker_model = TensorFlowModel(model_data=MODEL_TAR_ON_S3, role=role, image_uri=tensorflow_image) transformer = sagemaker_model.transformer( instance_count = 1, instance_type = instance_type, strategy='MultiRecord', max_concurrent_transforms=8, max_payload=10, # 单位MB output_path = output_data_path, ) transformer.transform(data = input_data_path, job_name = job_name, content_type = 'application/json', logs=False, wait=True )
日志片段
模型加载耗时很长,期间出现这些错误和警告:
2020-11-08T15:14:12.433+01:00 2020/11/08 14:14:12 [error] 14#14: *3066 no live upstreams while connecting to upstream, client: 169.254.255.130, server: , request: "GET /ping HTTP/1.1", subrequest: "/v1/models/my_model:predict", upstream: "http://tfs_upstream/v1/models/my_model:predict", host: "169.254.255.131:8080"
2020-11-08T15:14:12.433+01:00 169.254.255.130 - - [08/Nov/2020:14:14:12 +0000] "GET /ping HTTP/1.1" 502 157 "-" "Go-http-client/1.1"
...(其他502错误日志)
还有:
successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
No warmup data file found at /opt/ml/model/export/my_model/1/assets.extra/tf_serving_warmup_requests
[warn] getaddrinfo: address family for nodename not supported
结合你的配置和日志,我来拆解一下这个问题:核心是模型已经加载到GPU(所以显存占满),但推理计算完全落到了CPU上,导致GPU利用率为0。下面是针对性的解决思路:
1. 优先升级TensorFlow版本(TF 2.0的批量推理GPU坑)
你用的TF 2.0.0是比较早期的版本,SageMaker的TF 2.0推理容器在Batch Transform模式下,存在TensorFlow Serving没有正确绑定GPU的已知问题——哪怕GPU存在,批量请求也会默认 fallback到CPU计算。
解决办法:
- 直接升级到TF 2.3+的GPU镜像,比如
763104351884.dkr.ecr.eu-central-1.amazonaws.com/tensorflow-inference:2.3.0-gpu,新版本容器修复了大量批量推理的GPU调度bug。 - 如果必须保留TF 2.0,就在创建
TensorFlowModel时添加环境变量,强制Serving使用GPU:sagemaker_model = TensorFlowModel( model_data=MODEL_TAR_ON_S3, role=role, image_uri=tensorflow_image, env={ 'TF_FORCE_GPU_ALLOW_GROWTH': 'true', 'CUDA_VISIBLE_DEVICES': '0' } )
2. 检查输入格式与模型签名的匹配度
你的模型签名定义的输入是image_bytes(原始图片字节),但批量转换用的content_type='application/json'——如果你的输入是JSON格式的像素数组,而非原始图片字节,TensorFlow Serving会在CPU上做格式转换和预处理,进而导致整个推理流程落到CPU,GPU只用来存储模型权重。
调整建议:
- 如果输入是原始图片文件,把
content_type改成application/x-image; - 如果输入是JSON格式的像素数据,修改模型导出时的签名,把输入名改成和JSON字段匹配的名称(比如
inputs={"input": model.input}),确保数据能直接传到GPU张量中。
3. 优化批量转换的并发配置
你设置的max_concurrent_transforms=8可能超出了ml.p3.2xlarge的GPU处理能力,导致请求排队,反而让GPU看起来“没干活”。另外MultiRecord策略需要模型支持批量输入才能发挥作用。
调整建议:
- 先把
max_concurrent_transforms降到2-4,观察GPU利用率变化,找到合适的并发数; - 确认模型输入形状是
(None, height, width, channels)(支持批量输入),这样MultiRecord才能把多个图片打包成一个批量请求,让GPU并行处理。
4. 补充模型预热文件(辅助优化)
日志里的No warmup data file found虽然不是直接原因,但模型加载后没有预热请求,第一次推理会初始化GPU上下文,导致启动阶段慢,也可能让Serving没有正确绑定GPU。你可以生成预热请求文件放到模型的assets.extra目录下:
- 用TensorFlow的SavedModel Warmup API生成
tf_serving_warmup_requests文件,放到export/1/assets.extra/目录后再打包模型上传到S3,让Serving启动时就初始化GPU环境。
关于其他日志警告
NUMA node警告是容器和实例的NUMA配置不匹配,属于环境兼容问题,不影响GPU使用,无需处理;502 Bad Gateway是模型加载过慢导致的健康检查临时失败,等模型加载完成后会自动恢复,和GPU利用率无关。
内容的提问来源于stack exchange,提问作者phi_abs

