网站建设建设,松江php网站开发培训,服装技术支持东莞网站建设,自动备份wordpress最近在昇腾平台上跑Qwen3-30B的训练任务#xff0c;要用混合精度加速。PyTorch原生的AMP在昇腾上支持不太好#xff0c;查了一圈发现得用Apex for Ascend。网上教程不少#xff0c;但都是基于官方容器的#xff0c;我们这边用的是自己的基础镜像#xff0c;按照官方文档编…最近在昇腾平台上跑Qwen3-30B的训练任务要用混合精度加速。PyTorch原生的AMP在昇腾上支持不太好查了一圈发现得用Apex for Ascend。网上教程不少但都是基于官方容器的我们这边用的是自己的基础镜像按照官方文档编译直接翻车。这篇文章记录完整的编译过程和遇到的几个大坑。一、为什么要用Apex1.1 混合精度训练大模型训练最头疼的就是显存不够和速度慢。混合精度训练能在几乎不掉精度的情况下训练速度提升2-3倍显存占用减半原理很简单计算密集的算子用FP16精度敏感的算子用FP32。Apex帮你自动处理这个切换不用手动改代码。1.2 昇腾为啥要适配NVIDIA的Apex直接调CUDA算子在昇腾上跑不了。Apex for Ascend做了两件事把CUDA算子替换成CANN算子保持API不变用户代码不用改代码仓库昇腾版https://gitcode.com/Ascend/apex原版https://github.com/NVIDIA/apex二、网络配置2.1 为什么要配代理编译过程需要拉取镜像和下载依赖包网络不通的话啥都干不了。很多人以为在终端里export一下就行了其实不够。很多同学以为设置了export http_proxy就万事大吉,但实际上:用户Shell → Docker守护进程 → 容器内进程 ↓ ↓ ↓ 需要代理 需要代理 需要代理需要配置三层Shell环境影响curl、git等命令Docker守护进程影响镜像拉取容器内环境影响pip安装2.2 Shell环境代理# 替换成实际的代理地址 export http_proxyhttp://10.1.2.3:8080 export https_proxyhttp://10.1.2.3:8080 export no_proxylocalhost,127.0.0.1 # 测试一下 curl -I https://www.google.com这个配置重启终端就失效了想永久生效写到~/.bashrc。2.3 Docker守护进程代理Docker daemon作为系统服务运行,不继承Shell环境变量,必须单独配置。检查当前配置:docker info | grep -i proxy配置步骤:创建配置目录:sudo mkdir -p /etc/systemd/system/docker.service.d创建HTTP代理配置cat /etc/systemd/system/docker.service.d/http-proxy.conf EOF [Service] EnvironmentHTTP_PROXYhttp://${PROXY_IP}:${PROXY_PORT} EnvironmentNO_PROXYlocalhost,127.0.0.1,docker-registry.example.com EOF创建HTTPS代理配置(https-proxy.conf):cat /etc/systemd/system/docker.service.d/https-proxy.conf EOF [Service] EnvironmentHTTPS_PROXYhttp://${PROXY_IP}:${PROXY_PORT} EOF重载并重启Docker服务:sudo systemctl daemon-reload sudo systemctl restart docker # 验证配置生效 docker info | grep -i proxy排查技巧: 如果配置后仍无法拉取镜像,检查:代理服务器是否允许Docker daemon的IP访问防火墙规则是否拦截/var/log/docker.log中的错误信息如果还是拉不了镜像检查一下防火墙和代理服务器的访问控制。三、官方容器编译先说一下官方推荐的流程作为对照。3.1 构建镜像首先在我们的环境中直接拉取Apex的镜像git clone -b master https://gitcode.com/Ascend/apex.git这步会比较慢等三四分钟左右然后切换到apex目录cd apex根据CPU架构选择因为我们的主机是x86_64架构所以选择cd scripts/docker/X86如果是ARM就需要选择下面的指令cd scripts/docker/X86 # x86_64 # cd scripts/docker/ARM # ARM上面的工作做完之后呢直接去构建我们的镜像即可docker build -t apex-builder:v1 .3.2 启动容器镜像配置完成之后我们直接启动容器这里需要-v参数把代码挂载进去编译产物会同步到宿主机docker run -it \ -v $(pwd)/apex:/home/apex \ --name apex-compile \ apex-builder:v1 bash3.3 安装环境进入容器之后首先安装torchpip install torch2.1.0 --index-url https://download.pytorch.org/whl/cpu然后去验证我们的torch是否安装成功这里显示版本号就说明已经安装成功了python3 -c import torch; print(torch.__version__)这里一定要注意是指令python3如果是python的话就很容易报错。3.4 自定义镜像编译我们用的是MindIE的openEuler镜像先装基础依赖# 更新系统 yum update -y # 编译工具 yum install -y gcc gcc-c make cmake git # Python开发包 yum install -y python38-devel # torch pip install torch2.1.0然后就可以开始执行编译cd /home/apex bash scripts/build.sh --python3.8四、踩坑记录4.1 镜像拉取失败执行docker build的时候报错Get https://registry-1.docker.io/...dial tcp: i/o timeout或者toomanyrequests: You have reached your pull rate limit原因就是Docker守护进程没配代理按照前面的方法配置就行。如果不想配代理可以用国内镜像源# 编辑/etc/docker/daemon.json { registry-mirrors: [ https://docker.mirrors.ustc.edu.cn, https://hub-mirror.c.163.com ] } sudo systemctl restart docker4.2 找不到libtorch.so这是最坑的一个问题。编译到最后报错/usr/bin/ld: cannot find -ltorch collect2: error: ld returned 1 exit status一开始以为是torch没装上用Python测试了一下python3.8 -c import torch; print(torch.__file__)输出/usr/local/lib64/python3.8/site-packages/torch/__init__.pytorch装在lib64下没问题啊。然后又试了找文件find / -name libtorch.so 2/dev/null发现torch安装在font stylecolor:rgb(216,57,49);/usr/local/lib64/python3.8/site-packages//font,而非font stylecolor:rgb(216,57,49);/usr/local/lib//font。那为什么链接器找不到呢看了一下编译脚本查看font stylecolor:rgb(216,57,49);apex/scripts/build.sh/font:scripts/build.sh调用的是setup.py在font stylecolor:rgb(216,57,49);apex/setup.py/font中搜索font stylecolor:rgb(216,57,49);torch/font关键字:搜索一下里面的路径相关代码找到了这个函数def get_package_dir(): if --user in sys.argv: package_dir site.USER_SITE else: package_dir f{sys.prefix}/lib/python{py_version}/site-packages return package_dir问题找到了脚本硬编码了/lib/但openEuler上Python装在/lib64/下。lib和lib64的区别这不是bug是Linux发行版的历史遗留设计。Red Hat系openEuler、CentOS、RHEL/usr/local/ ├── lib/ # 32位库 └── lib64/ # 64位库Debian系Ubuntu、Debian/usr/local/ └── lib/ └── x86_64-linux-gnu/ # 64位库Red Hat明确区分32位和64位库Debian用子目录区分。Python的安装路径取决于包管理器安装遵循发行版规范源码编译看configure参数pip安装继承Python解释器的配置解决办法方法一改setup.py直接修正路径逻辑def get_package_dir(): if --user in sys.argv: package_dir site.USER_SITE else: # 改这里 package_dir f{sys.prefix}/lib64/python{py_version}/site-packages return package_dir然后直接编译cd /home/apex python3.8 setup.py --cpp_ext bdist_wheel注意不要再用scripts/build.sh因为它会重新clone代码把你的修改覆盖掉。方法二建软链接不改代码建个符号链接绕过ln -s /usr/local/lib64/python3.8/site-packages \ /usr/local/lib/python3.8/site-packages这个方法简单快速但可能影响其他程序。方法三虚拟环境最推荐的方式python3.8 -m venv /opt/apex-env source /opt/apex-env/bin/activate pip install torch2.1.0 cd /home/apex python setup.py --cpp_ext bdist_wheel虚拟环境统一用lib/路径不会有lib64问题。4.3 指令错误刚开始的指令是python -c “import torch; print(torch.version)”会发现抛出错误bash: python: command not found需要我们换一个Python指令也就是需要把Python版本几去指出来这里python3是最常见的换成这个指令即可python3 -c “import torch; print(torch.version)”。五、实验测试实验测试分为两个阶段基础环境验证和混合精度性能对比。基础测试是用来确定环境是否可行性能对比测试则聚焦 Apex AMP 混合精度训练的作用也就是是否可以提升训练速度并降低显存占用。5.1 基础测试基础测试的核心目标是校验环境是否可以避免因环境配置问题导致后续训练测试失败。import torch from apex import amp print(fTorch: {torch.__version__}) print(fApex available: {amp is not None}) # 补充NPU环境校验昇腾平台必备 print(fNPU是否可用: {torch.npu.is_available()}) print(f当前NPU设备ID: {torch.npu.current_device() if torch.npu.is_available() else 无})测试结果如下Torch: 2.1.0Apex available: TrueNPU是否可用: True当前NPU设备ID: 0说明已经可以正常运行了。5.2 混合精度训练测试写个完整的脚本测试一下import torch from apex import amp import time # 创建模型 model torch.nn.Sequential( torch.nn.Linear(1024, 2048), torch.nn.ReLU(), torch.nn.Linear(2048, 1024), torch.nn.ReLU(), torch.nn.Linear(1024, 512) ).npu() optimizer torch.optim.Adam(model.parameters(), lr0.001) # 初始化混合精度 model, optimizer amp.initialize(model, optimizer, opt_levelO1) print(开始训练...) # 准备数据 x torch.randn(64, 1024).npu() target torch.randn(64, 512).npu() # 预热 for _ in range(10): output model(x) loss torch.nn.functional.mse_loss(output, target) with amp.scale_loss(loss, optimizer) as scaled_loss: scaled_loss.backward() optimizer.step() optimizer.zero_grad() # 测试FP32 model_fp32 torch.nn.Sequential( torch.nn.Linear(1024, 2048), torch.nn.ReLU(), torch.nn.Linear(2048, 1024), torch.nn.ReLU(), torch.nn.Linear(1024, 512) ).npu() optimizer_fp32 torch.optim.Adam(model_fp32.parameters(), lr0.001) torch.npu.synchronize() start time.time() for _ in range(100): output model_fp32(x) loss torch.nn.functional.mse_loss(output, target) loss.backward() optimizer_fp32.step() optimizer_fp32.zero_grad() torch.npu.synchronize() fp32_time time.time() - start # 测试AMP torch.npu.synchronize() start time.time() for _ in range(100): output model(x) loss torch.nn.functional.mse_loss(output, target) with amp.scale_loss(loss, optimizer) as scaled_loss: scaled_loss.backward() optimizer.step() optimizer.zero_grad() torch.npu.synchronize() amp_time time.time() - start print(f\nFP32训练: {fp32_time:.2f}秒) print(fAMP训练: {amp_time:.2f}秒) print(f加速比: {fp32_time/amp_time:.2f}x)输出结果如下给我们的结果显示FP32训练: 8.43秒同时AMP训练: 4.21秒加速比: 2.00xAMP 混合精度训练耗时 4.21 秒纯 FP32 训练耗时 8.43 秒有了近两倍的加速这一结果符合混合精度训练的预期。六、总结Apex编译看似简单,实则暗藏许多细节。本文通过真实案例,深入剖析了从网络代理到系统库路径的各个环节。在自定义镜像上编译Apex for Ascend主要坑点总结为以下三点Docker守护进程代理配置容易漏lib和lib64路径差异编译脚本会覆盖手动修改希望大家可以学习一些经验教训对于大模型训练来说Apex基本是必备工具。昇腾适配版虽然有些小坑但整体可用性还不错注明昇腾PAE案例库对本文写作亦有帮助。