使用OSS加速器可以显著提升数据集加载速度,从而提升整体的模型训练速度。本文基于大量性能测试对比了使用和未使用OSS加速器的加速效果。说明在GPU利用率尚未达到瓶颈的情况下,数据加载效率至关重要。此外,本文以预训练模型ResNet-18在Imagenet ILSVRC数据集上进行微调的训练任务为例,指导您如何在GPU云服务器中使用OSS加速器来提升模型训练速度。
加速效果
对比标准OSS Bucket,OSS加速器展现出了显著的性能优势。凭借其低延迟特性,OSS加速器在使用较少的worker数量时便能实现更高的吞吐量表现。在多组实验中,OSS加速器提升训练效率40%~400%,大幅降低了计算资源的消耗与使用成本,为用户提供了更高效的解决方案。
方案概览
在GPU云服务器上使用OSS加速器加速加载训练数据的过程如下:
要实现以上加速效果只需三步:
创建GPU云服务器:构建一个契合模型训练工作需求的GPU云服务器。
创建OSS Bucket并开通OSS加速器:创建一个OSS Bucket存储空间并开通OSS加速器,同时获取Bucket内网域名以及OSS加速器域名用于后续训练任务。
训练模型:在完成上述准备工作后,先对原始数据集进行预处理,再将其上传至OSS。随后,在训练过程中使用OSS加速器把数据集加载到本地,以此开展模型的训练工作。
操作步骤
步骤一:创建GPU云服务器
以下步骤旨在创建并连接一个适用于模型训练任务的GPU云服务器实例。该实例的规格为ecs.gn6i-c4g1.xlarge,操作系统为Ubuntu 22.04、CUDA版本为12.4.1。需注意,自定义实例配置时,CUDA版本请选择最新版本。
1. 创建GPU云服务器
前往实例创建页。
选择自定义购买页签。
按需选择付费类型、地域、网络及可用区、实例规格、镜像等配置。完成创建。有关各配置项详细说明,请参见配置项说明。
本次实践ECS实例所采用规格为ecs.gn6i-c4g1.xlarge,仅供参考。
选择操作系统镜像以Ubuntu 22.04版本为例,并勾选安装GPU驱动选择CUDA版本为CUDA 版本 12.4.1,届时服务器启动时会自动安装CUDA环境,无需额外手动配置。
2. 连接GPU云服务器
在云服务器ECS控制台的实例列表页面,根据地域、实例ID找到创建好的ECS实例,单击操作列下的远程连接。
在远程连接对话框中,单击通过Workbench远程连接对应的立即登录。
在登录实例对话框中,选择认证方式为SSH密钥认证,用户名为
ecs-user
,输入或上传创建密钥对时下载的私钥文件,单击确定,即可登录ECS实例。说明私钥文件在创建密钥对时自动下载到本地,请您关注浏览器的下载记录,查找
.pem
格式的私钥文件。显示如下页面后,说明您已成功登录ECS实例且CUDA驱动已开始自动安装,只需等待安装完成即可。
步骤二:创建OSS Bucket并开通OSS加速器
以下步骤旨在与目标GPU云服务器同一地域下,创建一个用于存储数据集的Bucket并开启该Bucket的OSS加速器空间,以提高数据集的访问速度。需注意,云服务器和Bucket处于同一地域且通过内网域名访问不会产生任何流量费用。
创建Bucket并获取内网域名
重要请确保您所创建的Bucket与目标GPU云服务器位于同一地域,本此实践以杭州地域为例。
进入对象存储OSS控制台的Bucket列表页面,单击创建Bucket。
在创建Bucket面板,依据面板所给出的提示信息来完成Bucket的创建工作。
在目标Bucket概览页面,访问端口区域,复制ECS的VPC网络访问(内网)的Endpoint留作备用,以便在后续训练时上传数据集和checkpoint到目标Bucket。
开通OSS加速器并获取加速器域名
进入对象存储OSS控制台的Bucket列表页面,选择目标Bucket后在左侧导航栏,选择 进入OSS加速器页面
单击设置。选中我已阅读服务试用条款,单击下一步。
在创建OSS加速器面板设置加速器容量,本次实验以配置500 GB为例。单击下一步。
选择指定路径加速,并配置加速路径为数据集所在目录后单击确定,然后根据页面指引完成加速器的创建。
在OSS加速器界面复制加速器域名留作备用,以便在后续训练时用于从目标Bucket下载数据集。
步骤三:训练模型
以下步骤旨在GPU云服务器上,完成模型训练环境的配置、数据集的上传,以及使用OSS加速器域名来加速模型训练。
完整代码工程参见demo.tar.gz。
配置训练环境
准备conda环境并配置依赖项。
执行以下命令,下载并安装conda。
curl -L https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -o /tmp/miniconda.sh && bash /tmp/miniconda.sh -b -p /opt/conda/ && rm /tmp/miniconda.sh && /opt/conda/bin/conda clean -tipy && export PATH=/opt/conda/bin:$PATH && conda init bash && source ~/.bashrc && conda update conda
执行
vim environment.yaml
命令,创建并打开名为environment.yaml
的conda环境文件,添加以下配置后保存。name: py312 channels: - defaults - conda-forge - pytorch dependencies: - python=3.12 - pytorch>=2.5.0 - torchvision - torchaudio - transformers - torchdata - oss2
执行以下命令,基于conda环境文件创建名为py312的conda环境。
conda env create -f environment.yaml
执行
conda activate py312
命令,激活名为py312的conda环境。如图所示已成功激活。重要后续的操作步骤,请在已激活的conda环境中继续进行。
配置环境变量。
执行以下命令,配置上传数据集时所需的访问凭证。请注意,命令中的
<ACCESS_KEY_ID>
、<ACCESS_KEY_SECRET>
请分别替换为RAM用户的AccessKey ID、AccessKeySecret。有关如何创建AccessKey ID和AccessKeySecret请参见创建AccessKey。export OSS_ACCESS_KEY_ID=<ACCESS_KEY_ID> export OSS_ACCESS_KEY_SECRET=<ACCESS_KEY_SECRET>
配置OSS Connector。
执行以下命令,安装OSS Connector。
pip install osstorchconnector
执行以下命令,创建访问凭证配置文件。
mkdir -p /root/.alibabacloud && touch /root/.alibabacloud/credentials
执行
vim /root/.alibabacloud/credentials
命令,打开配置文件添加如下配置并保存。有关OSS Connector更多配置,请参见配置OSS Connector for AI/ML。使用AccessKey ID和AccessKey Secret作为访问凭证的配置示例,示例中的
<Access-key-id>
、<Access-key-secret>
请分别替换为RAM用户的AccessKey ID、AccessKeySecret。如何创建AccessKey ID和AccessKeySecret请参见创建AccessKey。{ "AccessKeyId": "LTAI************************", "AccessKeySecret": "At32************************" }
执行以下命令,设置credentials文件只读权限,以保障AK、SK密钥安全。
chmod 400 /root/.alibabacloud/credentials
执行以下命令,创建OSS Connector配置文件。
mkdir -p /etc/oss-connector/ && touch /etc/oss-connector/config.json
执行
vim /etc/oss-connector/config.json
命令,打开配置文件添加如下配置并保存。正常情况下使用此默认配置即可。{ "logLevel": 1, "logPath": "/var/log/oss-connector/connector.log", "auditPath": "/var/log/oss-connector/audit.log", "datasetConfig": { "prefetchConcurrency": 24, "prefetchWorker": 2 }, "checkpointConfig": { "prefetchConcurrency": 24, "prefetchWorker": 4, "uploadConcurrency": 64 } }
准备数据
上传训练数据集和验证数据集到目标Bucket。
执行以下命令下载训练数据集和验证数据集至云服务器。需注意,此数据集并非真实实验场景所采用数据集,仅作测试用途。
wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241216/jsnenr/n04487081.tar wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241218/dxrciv/n10148035.tar wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241216/senwji/val.tar
执行以下命令解压下载好的数据集,并在当前路径下创建dataset目录将数据集放入其中。
tar -zxvf n10148035.tar && tar -zxvf n04487081.tar && tar -zxvf val.tar mkdir dataset && mkdir ./dataset/train && mkdir ./dataset/val mv n04487081 ./dataset/train/ && mv n10148035 ./dataset/train/ && mv IL*.JPEG ./dataset/val/
执行
python3 upload_dataset.py
命令运行脚本,将解压好的数据集上传至指定的Bucket中。# upload_dataset.py from torchvision import transforms from PIL import Image import oss2 import os from oss2.credentials import EnvironmentVariableCredentialsProvider # # 以杭州区域内网域名为例 OSS_ENDPOINT = "oss-cn-hangzhou-internal.aliyuncs.com" #OSS内网访问域名 OSS_BUCKET_NAME = "<YourBucketName>" #目标Bucket名称 BUCKET_REGION = "cn-hangzhou" #目标Bucket地域 # OSS_URI_BASE: 自定义OSS bucket中的存储前缀 OSS_URI_BASE = "dataset/imagenet/ILSVRC/Data" def to_tensor(img_path): IMG_DIM_224 = 224 compose = transforms.Compose([ transforms.RandomResizedCrop(IMG_DIM_224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) img = Image.open(img_path).convert('RGB') img_tensor = compose(img) numpy_data = img_tensor.numpy() binary_data = numpy_data.tobytes() return binary_data def list_dir(directory): for root, _, files in os.walk(directory): rel_root = os.path.relpath(root, start=directory) for file in files: rel_filepath = os.path.join(rel_root, file) if rel_root != '.' else file yield rel_filepath IMG_DIR_BASE = "./dataset" """ IMG_DIR_BASE是本地存放图片的路径,绝对路径或相对路径都可以 该路径下结构应该和实际数据集结构一致,具体结构如下 {IMG_DIR_BASE}/ train/ n10148035/ n10148035_10034.JPEG n10148035_10217.JPEG ... n11879895/ n11879895_10016.JPEG n11879895_10019.JPEG ... ... val/ ILSVRC2012_val_00000001.JPEG ILSVRC2012_val_00000002.JPEG ... """ bucket_api = oss2.Bucket(oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider()), OSS_ENDPOINT, OSS_BUCKET_NAME, region=BUCKET_REGION) for phase in [ "val", "train"]: IMG_DIR = "%s/%s" % (IMG_DIR_BASE, phase) for _, img_relative_path in enumerate(list_dir(IMG_DIR)): img_bin_name = img_relative_path.replace(".JPEG", ".pt") object_key = "%s/%s/%s" % (OSS_URI_BASE, phase, img_bin_name) bucket_api.put_object(object_key, to_tensor("%s/%s" % (IMG_DIR,img_relative_path)))
下载图像数据集标签文件,用于构建数据集的分类映射关系。
wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241220/izpskr/imagenet_class_index.json wget https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241220/lfilrp/ILSVRC2012_val_labels.json
训练流程
构建用于处理ImageNet数据集的工具类。该类主要通过OSS加速器域名,从OSS加速器空间下载数据集并构建dataloader。
构建预训练ResNet18模型初始化工具类。
构建用于训练ResNet模型的工具类。该类通过给定的模型(model)、数据加载器(dataloaders),以及训练轮数(epoch_num)开展模型训练工作。
构建用于整合模型训练流程的主脚本文件。该文件整合以上多个工具类开启模型训练。
执行
python3 main.py
命令来开始模型训练,如图所示,已成功启动训练流程。
结果验证
进入Bucket列表选择目标Bucket,单击 后查看checkpoints目录下的resnet18.pt文件。如图所示,训练结束后checkpoint文件已成功上传至OSS。