首页 / 资讯中心 / 文章详情

ModelArts模型训练与部署实战避坑指南

ModelArts模型训练与部署实战避坑指南 ★ FEATURED ARTICLE
1. 这不是云上点点鼠标就完事的“傻瓜教程”而是我在ModelArts上踩了7次OOM、3次镜像拉取失败、2次API调用超时后亲手写下的真实训练-部署闭环笔记“基于华为云ModelArts完成模型训练与部署”——这个标题在技术社区里太常见了常见到让人下意识划走。但如果你真点进来大概率会发现内容要么是官方文档的搬运工式复述要么是“创建Notebook→上传数据→点击训练→一键部署”四步走的幻灯片式演示。这根本不是真实项目该有的样子。我去年在ModelArts上落地了4个生产级AI服务从OCR识别产线缺陷到NLP模型做客服工单自动归类再到时序模型预测设备故障。每一次上线前我都得在控制台反复刷新日志盯着GPU显存曲线像盯K线图一样紧张每一次部署失败报错信息里总藏着一个你根本想不到的坑比如/home/ma-user目录权限被自动重置、比如自定义镜像里pip install的包版本和ModelArts底层CUDA驱动不兼容、比如模型文件路径里多了一个看不见的空格……这些细节官方文档不会写因为它们不是“标准流程”而是你真实敲键盘时撞上的墙。这篇笔记就是我把所有这些墙的位置、厚度、怎么绕过去甚至怎么用锤子砸开全都记下来了。它不讲“什么是ModelArts”只讲“当你在训练任务里看到ResourceExhaustedError: OOM when allocating tensor时下一步该查哪三个地方”它不讲“模型部署有在线服务和批量服务两种”只讲“为什么你选了在线服务却在API调用时收到503错误而问题根源其实在你的config.json里少配了一行max_batch_size”。核心关键词就三个华为云、ModelArts、模型部署。如果你正卡在“模型训好了但不知道怎么让业务系统调用它”或者“部署成功了但一并发请求就崩”又或者“本地跑得好好的模型一上ModelArts就报NaN”那你来对地方了。这不是给初学者看的入门指南而是给已经把代码写好、数据准备好、就差最后一步推上线的工程师准备的一份带血的作战地图。2. 为什么非得用ModelArts不是因为“国产替代”而是因为它把“工程化”的成本压到了肉眼可见的低很多人一提ModelArts第一反应是“这是华为的云平台得学新东西”。这种想法会直接把你带进死胡同。ModelArts的价值从来不在“它是不是国产”而在于它把AI模型从实验室走向生产线的工程化鸿沟用一套高度集成的工具链给填平了。我们拆开看为什么其他方案在真实项目里会卡住脖子。首先是环境一致性。你在本地用RTX 4090训了个ResNet50PyTorch 2.1 CUDA 12.1一切完美。但当你想把模型部署到服务器上就得自己配Docker镜像、装驱动、调CUDA版本、解决libcudnn.so找不到的玄学问题。ModelArts的“训练作业”和“在线服务”共享同一套底层运行时环境。你选一个pytorch_2_1_0-cuda_11_8的镜像开始训练等模型导出后部署时直接选同一个镜像环境变量、动态库路径、Python包依赖全部原封不动继承过来。我试过把一个在本地pip install torch2.0.1cu117才能跑通的模型硬塞进ModelArts的pytorch_2_1_0-cuda_11_8环境里结果import torch直接报错。后来才发现ModelArts镜像里预装的torch是打了华为定制补丁的版本和PyPI上官方发布的二进制包ABI不兼容。解决方案别自己pip install老老实实用镜像自带的torch或者去ModelArts的“镜像市场”找对应版本的定制镜像。这个细节决定了你是在调试环境还是在调试模型本身。其次是资源调度的确定性。本地训练你最多能开几个进程显存够不够全凭你手动掐算。但在ModelArts上“按需付费”的背后是精确到秒的资源计量。我遇到过最典型的场景一个文本分类任务用RoBERTa中文预训练模型微调。本地跑batch_size16很稳但一上ModelArts选了p3.2xlarge1张V10016G显存的规格训练到第3个epoch就OOM。查日志发现不是模型太大而是DataLoader的num_workers设成了8每个worker都试图加载整个词表瞬间吃光显存。ModelArts的GPU监控面板里memory utilization曲线像心电图一样剧烈波动而GPU utilization却长期趴在20%以下。解决方案把num_workers从8降到2再把pin_memory设为True让数据预加载到GPU显存里而不是反复在CPU和GPU之间拷贝。这个调整让训练速度提升了37%而且全程稳定。这种细粒度的资源观测和调优能力在本地或普通云主机上你得自己搭PrometheusGrafana花两天时间才搞定。最后是部署链路的极简性。很多团队还在用FlaskGunicorn自己搭API服务然后用Nginx做反向代理和负载均衡。这没问题但当你要支持灰度发布、AB测试、自动扩缩容时工程复杂度指数级上升。ModelArts的“在线服务”模块本质上是一个托管的、可配置的推理引擎。你只需要提供一个符合规范的customize_service.py文件里面定义好model_fn加载模型、input_fn解析输入、predict_fn执行推理、output_fn格式化输出这四个函数剩下的——健康检查、流量路由、实例伸缩、日志聚合、指标监控——全部由平台接管。我上一个项目需要把EasyOCR训练好的自定义模型部署成API。如果自己搭服务光是处理不同尺寸图片的预处理逻辑、应对高并发下的内存泄漏、保证长连接稳定性就得写几百行胶水代码。而在ModelArts上我把easyocr.Reader的初始化逻辑放进model_fn把reader.readtext的调用放进predict_fn再加几行日志整个服务就活了。上线后平台自动给你生成一个HTTPS endpoint连证书都不用管。这才是“模型部署”该有的样子关注模型逻辑而不是运维细节。所以选择ModelArts不是为了赶时髦而是因为它把那些本该属于基础设施层的、枯燥且易错的工程工作打包成一个按钮、一个配置项、一个API调用。它让你能把100%的精力聚焦在模型本身——那个真正创造业务价值的东西上。3. 训练环节的“魔鬼在细节”从数据上传到模型保存每一步都藏着决定成败的参数在ModelArts上启动一个训练任务表面上看就是填几个表单选镜像、选规格、传数据、写启动命令。但正是这些看似简单的表单决定了你的训练是顺利收敛还是在第100个step就爆出NaN。我把整个训练流程拆成五个关键环节每个环节都附上我踩过的坑和实测有效的参数建议。3.1 数据上传与组织别让“路径错误”毁掉三天的训练ModelArts要求训练数据必须放在OBS对象存储服务桶里。这里第一个大坑是路径分隔符。Windows用户习惯用\Mac和Linux用/。OBS是标准的S3兼容存储只认/。如果你在本地用Python脚本生成数据清单如train.txt里面写的是data\img_001.jpg 0那么ModelArts在读取时会把它当成一个完整的文件名去OBS里找data\img_001.jpg这个对象结果当然是404。解决方案统一用/并在上传前用脚本清洗。我写了一个小函数def normalize_path_for_obs(path_str): 将任意路径字符串标准化为OBS兼容的Unix风格 return path_str.replace(\\, /).replace(//, /) # 使用示例 local_path rC:\project\data\train\001.jpg obs_path my-bucket/train/001.jpg # 注意OBS路径是 bucket_name/prefix # 清洗后的路径用于生成清单第二个坑是数据集结构。ModelArts的PyTorch镜像默认使用torchvision.datasets.ImageFolder它要求数据必须是严格的两级目录结构/class1/img1.jpg,/class2/img2.jpg。如果你的数据是扁平的或者类别名里有空格、中文、特殊符号ImageFolder会直接报错。我的做法是上传前用一个preprocess_data.py脚本把原始数据重命名、重分类。例如把cat (1).jpg变成cat_001.jpg把狗文件夹变成dog。这个脚本必须和训练代码一起打包上传作为训练作业的启动前步骤。第三个坑是OBS访问权限。很多人上传完数据训练任务一启动就报PermissionDenied。这是因为OBS桶的ACL访问控制列表默认是私有的。你必须在OBS控制台找到你的桶进入“权限管理”把“桶策略”设置为允许ModelArts服务角色访问。具体操作是添加一条策略Principal填acs:iam::[your-account-id]:role/ma-obs-access-roleAction填obs:GetObjectResource填acs:obs:::[bucket-name]/*。这个角色名在ModelArts的“全局配置”里可以查到千万别手敲复制粘贴最安全。3.2 启动命令与参数--data_dir不是可有可无的占位符训练作业的“启动命令”框是你和ModelArts底层容器交互的唯一入口。很多人在这里只写python train.py然后祈祷一切顺利。这几乎必然失败。正确的写法必须显式传递所有关键路径参数。以一个典型的PyTorch图像分类任务为例python train.py \ --data_dir /home/ma-user/work/data \ --output_dir /home/ma-user/work/output \ --model_name_or_path /home/ma-user/work/pretrained/resnet50 \ --per_device_train_batch_size 32 \ --learning_rate 1e-4 \ --num_train_epochs 10 \ --save_steps 500 \ --logging_steps 100 \ --fp16 \ --seed 42这里每一行都有讲究--data_dir /home/ma-user/work/data这是硬性规定。ModelArts会把OBS桶里你指定的路径自动挂载到容器内的这个固定位置。你代码里读数据必须从这里读不能写死./data或/data。--output_dir /home/ma-user/work/output同理所有模型权重、日志、中间文件都必须写到这个目录。ModelArts会自动把这里的内容同步回OBS。如果你写到/tmp或别的地方训练完就没了。--model_name_or_path如果你用的是Hugging Face的transformers库这个参数指向预训练模型。你可以把它放在OBS里然后在启动命令里用--model_name_or_path /home/ma-user/work/pretrained/roberta_chinese。注意/home/ma-user/work/pretrained这个目录需要在训练作业的“数据源”里额外添加一个OBS路径来挂载。--fp16开启混合精度训练。这对V100/A100显卡几乎是必选项能提升30%-50%的训练速度并减少显存占用。但要注意不是所有模型都支持特别是你自己写的、没经过apex或torch.cuda.amp适配的模型开了会直接报错。我的经验是先关掉--fp16跑通一轮再打开它加速。3.3 模型保存与导出.pth不是终点saved_model才是部署的起点训练完成后你得到的通常是一个.pth文件比如pytorch_model.bin。但这只是PyTorch的权重文件不能直接部署。ModelArts的在线服务要求模型必须是SavedModel格式TensorFlow或TorchScript格式PyTorch。对于PyTorch你必须在训练代码的最后加上模型导出逻辑。# 在train.py的最后训练循环结束后 def save_torchscript_model(model, input_sample, output_path): 将PyTorch模型导出为TorchScript格式 model.eval() # 切换到评估模式 traced_script_module torch.jit.trace(model, input_sample) traced_script_module.save(output_path) # 使用示例假设你的模型输入是 [1, 3, 224, 224] 的tensor dummy_input torch.randn(1, 3, 224, 224).to(device) save_torchscript_model(model, dummy_input, /home/ma-user/work/output/model.pt)关键点在于input_sample。它必须是和你实际推理时完全一致的shape和dtype。如果你的模型在推理时接受的是[B, C, H, W]的图片那这里就必须用同样shape的dummy tensor。否则导出的model.pt在部署时会报Input type mismatch。我曾经因为dummy_input用了float64而模型期望float32导致部署后API返回全是零排查了整整一天。导出的model.pt文件必须放在--output_dir指定的目录下ModelArts才能在部署时自动找到它。同时你还需要一个config.json文件描述模型的输入输出规范。这个文件不是可选的没有它部署会失败。一个最小可用的config.json长这样{ inputs: [ { name: input, shape: [1, 3, 224, 224], dtype: float32 } ], outputs: [ { name: output, shape: [1, 1000], dtype: float32 } ] }shape里的1是batch size表示模型支持的最小batch。dtype必须和你dummy_input的dtype严格一致。这个JSON文件也必须和model.pt放在同一个目录下。3.4 日志与监控别等训练完了才去看要像盯盘一样实时看ModelArts的训练作业页面有一个“日志”标签页。但很多人只在训练结束时点开看一眼。这是巨大的浪费。你应该在训练启动后就打开这个页面把浏览器窗口钉在一边像盯股票一样盯它的输出。重点关注三类日志资源日志开头几行会有GPU memory usage: xxx MB / yyy MB。如果这个数字一路飙升逼近yyy说明显存快满了随时可能OOM。这时你应该立刻暂停任务回去检查batch_size和num_workers。Loss日志你的训练脚本里应该每logging_steps就打印一次loss。正常情况下loss应该是一个平滑下降的曲线。如果loss突然跳变比如从0.23跳到inf或nan那就是模型崩溃的前兆。常见原因有学习率太大、梯度爆炸、数据里有脏样本比如全黑的图片、长度为0的文本。我的做法是一旦看到nan立刻停止训练用git checkout回退到上一个稳定的checkpoint然后降低学习率10倍重新开始。Warning日志比如UserWarning: Using a target size (torch.Size([16, 1])) that is different from the input size (torch.Size([16]))。这种warning看起来无害但它往往预示着后续的RuntimeError。宁可花10分钟搞懂这个warning也不要等到报错再查。ModelArts还提供了“性能分析”功能可以生成GPU利用率、显存占用、IO吞吐的详细图表。我建议每个重要的训练任务都开启这个功能。它能帮你发现很多隐藏的瓶颈。比如我发现一个NLP任务GPU利用率长期低于30%但IO吞吐很高说明瓶颈在数据加载。于是我把DataLoader的prefetch_factor从2调到4性能立刻提升了22%。4. 部署环节的“生死时速”从服务创建到API调用每一个配置都是线上服务的命门训练完成模型导出你以为就万事大吉了不部署才是真正的“生死时速”。一个配置项填错服务就起不来一个参数设小了业务方一调用就503一个路径写错了API永远返回空。我把部署过程拆解为四个核心动作每个动作都附上“必填项”、“易错项”和“救命技巧”。4.1 创建在线服务镜像、模型、配置三者必须严丝合缝在ModelArts控制台点击“部署”-“在线服务”进入创建向导。这里的第一步是选择“镜像来源”。你有两个选择使用ModelArts内置镜像或使用自定义镜像。绝大多数情况下选前者。内置镜像经过华为深度优化和充分测试稳定性远高于自己Docker build的镜像。我曾经为了追求“最新版PyTorch”自己build了一个pytorch:2.2.0-cuda12.1的镜像结果部署后torch.cuda.is_available()返回False查了两天才发现是CUDA驱动版本和ModelArts底层不匹配。后来换回ModelArts官方的pytorch_2_2_0-cuda_12_1镜像问题立刻消失。第二步是“模型来源”。这里必须选择你训练作业的“输出路径”也就是/home/ma-user/work/output在OBS里对应的桶路径。关键点来了路径末尾不能有斜杠。如果你填的是obs://my-bucket/output/ModelArts会认为这是一个目录然后去里面找model.pt和config.json。但如果路径写成obs://my-bucket/output没有末尾斜杠它就会把这个路径当作一个“模型包”的根目录。我第一次部署就栽在这里填了带斜杠的路径服务状态一直卡在“创建中”日志里全是File not found: model.pt。删掉斜杠5秒内服务就起来了。第三步是“资源配置”。这里有两个核心参数实例规格和实例数量。实例规格不要盲目追求高配。p3.2xlarge1V100适合大多数CV模型c7.large2核8G足够跑一个轻量级的RoBERTa文本分类。我见过最离谱的案例一个只有10万参数的LSTM模型被配了p4d.24xlarge8A100结果服务启动后CPU利用率常年1%纯属浪费钱。我的经验是先用最小规格如c7.large创建服务用curl发10个并发请求看响应时间和错误率。如果一切正常再逐步降配直到找到性能和成本的平衡点。实例数量初始值填1。ModelArts的自动扩缩容功能非常强大你只需要在“高级设置”里把“最小实例数”设为1“最大实例数”设为5“目标CPU利用率”设为60%。这样当QPS每秒查询率超过阈值服务会自动扩容当流量回落又会自动缩容。比你手动增减实例既省钱又省心。4.2 自定义服务代码customize_service.py不是模板而是你的业务逻辑中枢ModelArts要求你提供一个customize_service.py文件它定义了服务的四个核心函数。很多人直接复制官方示例改改模型路径就完事。这是大忌。这个文件是你模型和外部世界交互的唯一接口必须根据你的业务需求深度定制。# customize_service.py import os import json import torch from PIL import Image import numpy as np from torchvision import transforms # 1. model_fn: 加载模型只在服务启动时执行一次 def model_fn(model_dir): model_dir: ModelArts自动挂载的模型目录即你OBS里存放model.pt和config.json的路径 # 加载TorchScript模型 model_path os.path.join(model_dir, model.pt) model torch.jit.load(model_path) model.eval() # 将模型移到GPU如果可用 device torch.device(cuda if torch.cuda.is_available() else cpu) model.to(device) # 返回一个字典包含模型和设备 return {model: model, device: device} # 2. input_fn: 解析HTTP请求的输入 def input_fn(request_body, request_content_type): request_body: 原始的bytes数据 request_content_type: 请求头里的Content-Type如application/json if request_content_type application/json: # 解析JSON假设输入是{image_url: http://xxx.jpg} 或 {base64: xxx} input_data json.loads(request_body.decode(utf-8)) # 处理图片URL if image_url in input_data: import requests from io import BytesIO response requests.get(input_data[image_url]) image Image.open(BytesIO(response.content)).convert(RGB) # 处理base64编码 elif base64 in input_data: import base64 from io import BytesIO image_bytes base64.b64decode(input_data[base64]) image Image.open(BytesIO(image_bytes)).convert(RGB) else: raise ValueError(Invalid input format. Must contain image_url or base64) # 图片预处理resize, normalize等 transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) input_tensor transform(image).unsqueeze(0) # 添加batch维度 return input_tensor else: raise ValueError(fUnsupported content type: {request_content_type}) # 3. predict_fn: 执行模型推理 def predict_fn(input_object, model_dict): input_object: input_fn返回的预处理后的tensor model_dict: model_fn返回的字典 model model_dict[model] device model_dict[device] # 将输入tensor移到设备上 input_tensor input_object.to(device) # 推理 with torch.no_grad(): output model(input_tensor) return output # 4. output_fn: 格式化输出返回给客户端 def output_fn(prediction_output, content_type): prediction_output: predict_fn返回的tensor content_type: 期望的返回类型如application/json if content_type application/json: # 将tensor转为list并取top-5 probabilities torch.nn.functional.softmax(prediction_output, dim1)[0] top_probs, top_indices torch.topk(probabilities, k5) # 假设你有一个label_map.json文件映射index到label名 label_map_path os.path.join(os.path.dirname(__file__), label_map.json) with open(label_map_path, r) as f: label_map json.load(f) result [] for i in range(len(top_indices)): idx int(top_indices[i].item()) prob float(top_probs[i].item()) label label_map.get(str(idx), funknown_{idx}) result.append({label: label, probability: prob}) return json.dumps({predictions: result}, ensure_asciiFalse) else: raise ValueError(fUnsupported accept type: {content_type})这个文件的关键点在于model_fn里一定要用torch.jit.load而不是torch.load因为后者加载的是state_dict无法直接执行。input_fn里必须处理各种可能的输入格式URL、base64、multipart form-data并做严格的异常处理。一个未捕获的requests.exceptions.ConnectionError会导致整个服务实例崩溃。predict_fn里一定要加with torch.no_grad():否则会累积计算图耗尽显存。output_fn里ensure_asciiFalse很重要否则中文label会变成\u4f60\u597d这样的乱码。4.3 API调用与压测别信“部署成功”要用真实流量验证服务状态显示“运行中”不代表它真的能用。你必须用真实的HTTP请求去验证。ModelArts会为每个在线服务生成一个唯一的HTTPS endpoint形如https://xxxxx.modelarts.cn-north-1.myhuaweicloud.com/v1/{project_id}/services/{service_name}/versions/latest。最基础的测试用curl# 测试一个图片URL curl -X POST https://xxxxx.modelarts.cn-north-1.myhuaweicloud.com/v1/xxx/services/my-ocr-service/versions/latest \ -H Content-Type: application/json \ -H Authorization: Bearer $(cat ~/.huaweicloud/access_token) \ -d {image_url: https://example.com/test.jpg} # 测试base64图片 curl -X POST https://xxxxx.modelarts.cn-north-1.myhuaweicloud.com/v1/xxx/services/my-ocr-service/versions/latest \ -H Content-Type: application/json \ -H Authorization: Bearer $(cat ~/.huaweicloud/access_token) \ -d {base64: iVBORw0KGgoAAAANSUhEUgAA...}注意Authorization头。ModelArts的API需要IAM Token认证。你不能用AK/SK直接签名必须先调用IAM的/v3/auth/tokens接口获取一个短期token。我写了一个简单的Python脚本get_token.py每次调用前运行它把token存到文件里curl命令里再读出来。这个细节官方文档里写得非常隐晦。更关键的是压测。用abApache Bench或wrk模拟真实业务流量# 用ab进行100并发总共1000次请求的压测 ab -n 1000 -c 100 -H Authorization: Bearer $(cat token) \ -T application/json \ -p test_payload.json \ https://xxxxx.modelarts.cn-north-1.myhuaweicloud.com/v1/xxx/services/my-ocr-service/versions/latest观察两个核心指标Requests per second如果这个数字远低于你的预期比如你期望100 QPS实测只有20说明模型推理太慢需要优化模型或升级实例规格。Failed requests如果有失败要看失败的原因。如果是Connect timeout说明服务实例数不够需要调高“最大实例数”如果是Receive error说明模型在处理某个特定输入时崩溃了需要检查input_fn的健壮性。我曾经在一个OCR服务上线前用ab压测发现100并发下失败率高达30%。查日志发现是input_fn里处理base64时没有做长度校验一个超长的base64字符串导致base64.b64decode内存溢出。加了一行if len(base64_str) 10 * 1024 * 1024: raise ValueError(Base64 string too long)问题立刻解决。4.4 监控与告警把“服务健康”变成可量化的数字ModelArts的“在线服务”页面有一个“监控”标签页。这里不是摆设而是你线上服务的“生命体征监护仪”。必须把以下三个指标加入你的日常巡检清单指标名称正常范围异常表现应对措施服务实例CPU使用率30% - 70%长期90%立即扩容实例或检查模型是否有死循环服务实例内存使用率 85%95%且持续上升检查input_fn是否在缓存大量数据或predict_fn是否有内存泄漏API平均响应时间(P95) 1000ms2000ms检查模型是否过大或实例规格是否不足更重要的是设置告警。在ModelArts控制台进入“告警管理”创建一个新的告警规则告警对象选择你的在线服务告警指标选择“API平均响应时间(P95)”触发条件 2000毫秒持续5分钟通知方式邮件 企业微信华为云支持对接我给自己设了三条告警响应时间超2秒、错误率超5%、实例CPU超90%。有一次半夜企业微信弹出告警说响应时间飙到5秒。我登录控制台一看P95是4800ms但CPU只有40%。这说明问题不在计算而在IO。查日志发现是input_fn里调用的外部图片URL有一个CDN节点挂了导致requests.get超时。我把图片下载逻辑改成带超时和重试timeout(3, 10), retries2问题就解决了。如果没有这个告警这个故障可能会持续到第二天早上影响所有业务。5. 实战避坑手册那些只在深夜debug时才会浮现的“幽灵问题”再完美的流程也挡不住现实世界的复杂性。下面这些是我和团队在过去一年里在ModelArts上遇到的、最诡异、最耗时、也最有价值的“幽灵问题”。它们不会出现在任何官方文档里但每一个都曾让我们在凌晨三点对着屏幕抓狂。5.1 “模型明明加载了但预测结果全是0”torch.no_grad()的隐形陷阱这个问题发生在我部署一个Melotts中文语音合成模型时。模型在本地Jupyter里跑得好好的一上ModelArtsAPI返回的音频波形振幅永远是0。查日志model_fn和predict_fn都执行成功没有任何报错。我花了整整8个小时用print语句一行行打点最终发现问题出在predict_fn里。Melotts的推理代码里有一段逻辑是# 错误的写法 with torch.no_grad(): # ... 一些计算 ... output model.inference(...) # 这个inference方法内部又调用了model.forward() # 问题model.forward()里有一段代码是 x x * mask而mask是一个requires_gradTrue的tensor # 结果output的grad_fn是None但它的某些中间变量grad_fn却不是None # 导致后续的audio post-processing 出错返回全零解决方案是把torch.no_grad()的范围精确地缩小到只包裹model.inference()这一行# 正确的写法 # ... 其他代码 ... with torch.no_grad(): output model.inference(...) # ... 其他代码 ...这个教训是torch.no_grad()不是万能的“防错开关”它会影响计算图的构建。对于复杂的、多阶段的模型尤其是语音、视频模型必须仔细阅读其源码理解其内部的梯度流再决定no_grad的边界在哪里。5.2 “服务启动了但API返回503 Service Unavailable”max_batch_size的无声杀手这个问题几乎每个部署过批量推理服务的人都会遇到。你创建了一个“批量服务”上传了1000张图片点击“执行”服务状态是“运行中”但API返回503。查服务日志里面有一行不起眼的警告WARNING: Batch size 1000 exceeds max_batch_size 128。原来ModelArts的批量服务有一个硬性限制单次请求的最大batch size。这个值默认是128而且不能在服务创建时修改。你只能在服务创建后进入“服务详情”-“编辑配置”在“高级设置”里找到max_batch_size手动把它调大。但这里有个坑max_batch_size不是你想设多大就多大。它受限于你选择的实例规格的显存。p3.2xlarge16G显存的理论最大值是256p4d.24xlarge40G显存的理论最大值是1024。如果你设了一个超出硬件能力的值服务会启动失败状态变成“异常”。我的做法是先用一个小batch比如32测试服务是否能正常工作然后逐步增加同时监控GPU显存。当显存占用率接近90%时当前的batch size就是你的安全上限。5.3 “本地训练的模型
阅读完成 · 觉得有帮助?
咨询建站