GPU迁移到NPU:手写数字识别
操作场景
在AI大模型训练与推理中,昇腾NPU作为国产算力平台,提供了与NVIDIA GPU对标的计算能力。对于已有基于GPU的PyTorch代码,开发者往往关心迁移成本与适配难度。torch_npu作为昇腾PyTorch适配包,使得标准PyTorch代码仅需极少量改动即可在NPU上运行,大幅降低迁移门槛。本教程适用于已有基于GPU的PyTorch训练代码、需迁移至昇腾NPU环境的开发者。
本教程以MNIST手写数字识别为例,详细介绍如何将GPU上的PyTorch训练代码迁移至昇腾NPU,通过对比GPU与NPU代码的差异,帮助开发者快速掌握迁移方法,并在ModelArts平台上完成训练与推理验证。
相关概念
| 概念 | 说明 |
|---|---|
| 昇腾NPU | 华为自研的AI处理器,提供与NVIDIA GPU对标的计算能力,搭载ARM架构系统,支持大模型训练与推理。 |
| CANN(Compute Architecture for Neural Networks) | 昇腾计算架构,是昇腾NPU的基础软件平台,类似于NVIDIA的CUDA,提供算子库、运行时和编译优化等能力。 |
| torch_npu | 昇腾PyTorch适配包,在PyTorch框架与CANN之间建立适配层,使标准PyTorch代码仅需少量改动即可在NPU上运行。 |
| CUDA(Compute Unified Device Architecture) | NVIDIA的并行计算平台和编程模型,GPU训练代码中常用的cuda相关API(如torch.cuda)均基于此。 |
迁移原理
torch_npu的工作原理是在PyTorch框架和昇腾CANN软件栈之间建立适配层,将PyTorch的CUDA调用自动转换为昇腾NPU的对应操作。因此,开发者无需重写模型逻辑,仅需替换设备相关的API调用即可完成迁移。
典型迁移场景:当您的业务需要从NVIDIA GPU集群迁移到昇腾NPU集群时(如国产化替代、成本优化等),可参照本案例的迁移方法,将现有PyTorch训练/推理代码快速适配至NPU环境。
| 功能 | GPU | NPU |
|---|---|---|
| 设备可用性 | torch.cuda.is_available() | torch.npu.is_available() |
| 张量移至设备 | .cuda() | .npu() |
| 设备指定 | torch.device("cuda") | torch.device("npu") |
| 加载模型映射 | map_location="cuda:0" | map_location="npu:0" |
| 设备监控 | nvidia-smi | npu-smi info |
期望效果:分别在GPU和NPU环境下完成MNIST手写数字识别模型的训练,对比迁移前后代码差异,验证NPU训练精度与GPU基本对齐。训练完成后将分别生成mnist_gpu.pt和mnist_npu.pt模型权重文件。
前提条件
- 已完成华为云账号注册、实名认证及相关权限授权。具体操作,请参见一、前置准备:账号与权限。
- Notebook实例的状态为运行中,且满足如下要求。如需创建新的Notebook实例,请参见创建Notebook实例。
实例规格、镜像和磁盘规格的详细说明如下表:
参数
NPU环境
GPU环境
说明
实例规格
推荐使用单卡规格(Ascend: 1*ascend snt9b1)或更高配置。
推荐使用单机1卡规格或更高配置。
GPU为可选项,用于交叉验证。
镜像
选择ModelArts预置镜像
pytorch_2.7.1-cann_8.3.rc1-py_3.11-hce_2.0.2509-aarch64-snt9b。
选择ModelArts预置镜像pytorch_1.12.1-cuda_10.2-py_3.9.11-ubuntu_20.04-x86_64。
需选择对应架构的镜像。
磁盘规格
建议5GB以上。
建议5GB以上。
用于存储数据集和模型权重。
计费说明
在ModelArts开发环境中运行Notebook实例时,会使用计算资源和存储资源,产生计算资源和存储资源的累计值计费。计费详情请参见开发环境计费项。
注意事项
迁移前请务必备份原始GPU代码和模型权重文件。架构差异(注意事项1)会导致X86镜像在NPU上完全不可用,请确认镜像架构匹配后再创建实例,避免资源浪费。
| 注意事项 | 说明 | 影响程度 |
|---|---|---|
| 架构差异 | 昇腾NPU搭载ARM系统,X86上构建的Docker镜像无法直接使用,需删除重新构建aarch64镜像 | 高 |
| import顺序 | import torch_npu必须在import torch之后、使用NPU功能之前导入 | 高 |
| 算子兼容 | 少数自定义CUDA算子需使用Ascend C重写,标准PyTorch算子一般无需修改 | 中 |
| 模型权重通用 | torch.save保存的权重文件在GPU和NPU间通用,仅map_location需对应调整 | 低 |
案例核心
本案例的核心是“环境验证 → 代码迁移 → 训练验证 → 推理对比”的闭环流程,能够清晰、直观地掌握PyTorch代码从GPU到NPU的迁移全貌。
迁移核心:仅需3处改动(参见步骤三)。
- 第1处,在import torch后添加import torch_npu。
- 第2处,将设备标识torch.cuda替换为torch.npu。
- 第3处,将设备标识cuda替换为npu,网络模型定义、训练逻辑、评估逻辑等代码无需任何修改。
权重通用:PyTorch保存的模型权重文件(.pt)在GPU和NPU间通用,仅需调整map_location参数即可跨设备加载。
监控对照:NPU使用npu-smi info替代GPU的nvidia-smi,其中AICore(%)对应NPU利用率,GPU-Util对应GPU利用率,HBM-Usage(MB)对应显存使用量。
步骤一:打开Notebook实例
- 登录ModelArts管理控制台,在左侧导航栏按需选择以下操作。
- 新版控制台:选择,进入“Notebook”页面。
- 旧版控制台:选择,进入“Notebook”页面。
- 在“Notebook”页面的“操作”列,单击“接入环境”,在“接入方式”对话框的“WebIDE”页签,单击“JupyterLab 接入”右侧的“接入”。
- 进入JupyterLab页面后,自动打开ModelArts Launcher页面。在“ModelArts Launcher”页面的“Notebook”区域,单击PyTorch,创建一个新的PyTorch Notebook。 图1 打开PyTorch
步骤二:环境验证
在开始迁移实践前,先验证当前运行环境是否可用。确认设备类型和计算能力正常后,再进行后续的代码迁移。
- 设备检测。 执行以下命令,自动检测当前运行环境是GPU、NPU还是CPU。
import torch if torch.cuda.is_available(): device = torch.device("cuda") print(f"当前环境:GPU - {torch.cuda.get_device_name(0)}") elif hasattr(torch, 'npu') and torch.npu.is_available(): import torch_npu device = torch.device("npu") print(f"当前环境:NPU - {torch.npu.get_device_name(0)}") else: device = torch.device("cpu") print("当前环境:CPU") print(f"设备标识:{device}")运行后应输出当前设备类型及设备标识,输出示例如下。如果输出“当前环境:CPU”,请检查镜像选择是否正确或资源规格是否分配成功。
- NPU输出示例:
当前环境:NPU - xxx 设备标识:npu
- GPU输出示例:
当前环境:GPU - xxx 设备标识:cuda
- NPU输出示例:
- 矩阵运算验证。
通过矩阵乘法验证设备计算能力。以下两个单元格分别对应GPU和NPU环境,根据当前运行环境执行。
- GPU矩阵运算验证:
import torch try: _has_gpu = torch.cuda.is_available() except Exception: _has_gpu = False if _has_gpu: print("===== GPU 矩阵运算 =====") x = torch.randn(10000, 10000).cuda() y = torch.randn(10000, 10000).cuda() z = x.mm(y) print(f"结果形状:{z.shape}") print(f"设备位置:{z.device}") print("GPU矩阵运算验证通过!") else: print("当前环境无GPU,跳过GPU矩阵运算验证")预期输出:
===== GPU 矩阵运算 ===== 结果形状:torch.Size([10000, 10000]) 设备位置:cuda:0 GPU矩阵运算验证通过!
- NPU矩阵运算验证:
import torch try: import torch_npu _has_npu = torch.npu.is_available() except Exception: _has_npu = False if _has_npu: print("===== NPU 矩阵运算 =====") x = torch.randn(10000, 10000).npu() y = torch.randn(10000, 10000).npu() z = x.mm(y) print(f"结果形状:{z.shape}") print(f"设备位置:{z.device}") print("NPU矩阵运算验证通过!") else: print("当前环境无NPU,跳过NPU矩阵运算验证")预期输出:
===== NPU 矩阵运算 ===== 结果形状:torch.Size([10000, 10000]) 设备位置:npu:0 NPU矩阵运算验证通过!
迁移要点:NPU版本仅增加了import torch_npu,并将.cuda() 替换为.npu(),其余代码完全一致。
验证方法:如果设备可用,应输出“矩阵运算验证通过!”及结果形状torch.Size([10000, 10000])。
- GPU矩阵运算验证:
步骤三:MNIST手写数字识别
本步骤完成MNIST手写数字识别的完整训练流程,包括:网络模型定义、数据准备与加载、训练与评估函数定义、GPU/NPU训练。其中仅训练部分的代码存在GPU与NPU差异,其余代码在两种环境下完全一致。
- 网络模型定义。
网络模型定义与设备无关,GPU和NPU无需任何差异。本案例使用LeNet-5变体卷积神经网络,适用于28×28灰度图像分类。网络包含2个卷积层(Conv2d)、2个Dropout层和2个全连接层(Linear),最终输出10类概率分布。
import torch import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(1, 32, 3, 1) self.conv2 = nn.Conv2d(32, 64, 3, 1) self.dropout1 = nn.Dropout(0.25) self.dropout2 = nn.Dropout(0.5) self.fc1 = nn.Linear(9216, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = self.conv1(x) x = F.relu(x) x = self.conv2(x) x = F.relu(x) x = F.max_pool2d(x, 2) x = self.dropout1(x) x = torch.flatten(x, 1) x = self.fc1(x) x = F.relu(x) x = self.dropout2(x) x = self.fc2(x) output = F.log_softmax(x, dim=1) return output print("网络模型定义完成")预期输出:
网络模型定义完成
- 数据准备。 下载MNIST数据集并构建数据加载器,该部分代码在GPU和NPU环境下完全一致。MNIST数据集提供以下两种下载方式,请根据网络环境选择:
下载方式
适用场景
说明
方式一:直接下载
网络可访问GitHub
从GitHub下载原始数据文件
方式二:OBS桶下载
网络受限环境
从华为云OBS桶下载已打包数据
- 下载方式一:直接下载
# 普通方式 !mkdir -p ./data/MNIST/raw !wget https://raw.githubusercontent.com/leo-mao/MNIST_data/master/train-images-idx3-ubyte.gz -O ./data/MNIST/raw/train-images-idx3-ubyte.gz !wget https://raw.githubusercontent.com/leo-mao/MNIST_data/master/train-labels-idx1-ubyte.gz -O ./data/MNIST/raw/train-labels-idx1-ubyte.gz !wget https://raw.githubusercontent.com/leo-mao/MNIST_data/master/t10k-images-idx3-ubyte.gz -O ./data/MNIST/raw/t10k-images-idx3-ubyte.gz !wget https://raw.githubusercontent.com/leo-mao/MNIST_data/master/t10k-labels-idx1-ubyte.gz -O ./data/MNIST/raw/t10k-labels-idx1-ubyte.gz
import os import gzip from torchvision import datasets, transforms os.makedirs('./data/MNIST/raw', exist_ok=True) # 解压 .gz for f in os.listdir('./data/MNIST/raw/'): if f.endswith('.gz'): with gzip.open(f'./data/MNIST/raw/{f}', 'rb') as gz: with open(f'./data/MNIST/raw/{f[:-3]}', 'wb') as out: out.write(gz.read()) - 下载方式二:OBS桶下载
# obs桶方式 !pip install download %env no_proxy='a.test.com,127.0.0.1,2.2.2.2' from download import download # 下载MNIST数据集 url = "https://eduhicomputing.obs.cn-south-1.myhuaweicloud.com:443/%20ComputerVision2/MNIST_Data.zip" path = download(url, "./data/MNIST/raw", kind="zip", replace=True) !mv ./data/MNIST/raw/MNIST_Data/test/* ./data/MNIST/raw/MNIST_Data/train/* ./data/MNIST/raw/ && rm -rf ./data/MNIST/raw/MNIST_Data
- 下载方式一:直接下载
- 加载数据集。使用torchvision加载MNIST数据集,创建训练集和测试集的DataLoader。
from torchvision import datasets, transforms transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) dataset1 = datasets.MNIST('./data', train=True, download=False, transform=transform) dataset2 = datasets.MNIST('./data', train=False, download=False, transform=transform) print(f"训练集大小:{len(dataset1)}") print(f"测试集大小:{len(dataset2)}")预期输出:
训练集大小:60000 测试集大小:10000
如果数据加载失败,请检查数据文件是否下载完整。
- 训练与评估函数。定义训练函数train和评估函数test,通过传入的device参数自动适配GPU或NPU,函数逻辑无需任何修改。
训练函数在每个batch中将数据和标签移至指定设备,评估函数统计损失和准确率。两个函数均通过device参数适配不同设备,无需修改。
def train(model, device, train_loader, optimizer, epoch): """训练模型,返回平均损失与准确率""" model.train() total_loss = 0 correct = 0 total = 0 for batch_idx, (data, target) in enumerate(train_loader): data, target = data.to(device), target.to(device) optimizer.zero_grad() output = model(data) loss = F.nll_loss(output, target) loss.backward() optimizer.step() total_loss += loss.item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() total += len(data) avg_loss = total_loss / len(train_loader) accuracy = 100. * correct / total print(f'Train Epoch: {epoch} | Loss: {avg_loss:.4f} | Accuracy: {correct}/{total} ({accuracy:.0f}%)') return avg_loss, accuracy def test(model, device, test_loader): """评估模型,返回平均损失与准确率""" model.eval() test_loss = 0 correct = 0 with torch.no_grad(): for data, target in test_loader: data, target = data.to(device), target.to(device) output = model(data) test_loss += F.nll_loss(output, target, reduction='sum').item() pred = output.argmax(dim=1, keepdim=True) correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(test_loader.dataset) accuracy = 100. * correct / len(test_loader.dataset) print(f'Test | Average loss: {test_loss:.4f} | Accuracy: {correct}/{len(test_loader.dataset)} ({accuracy:.0f}%)') return test_loss, accuracy print("训练与评估函数定义完成")预期输出:
训练与评估函数定义完成
- GPU/NPU训练。分别使用GPU和NPU进行模型训练,对比迁移前后代码差异。训练3个Epoch后保存模型权重文件。
- GPU训练:以下代码在GPU实例上运行。
import torch import torch.optim as optim from torch.optim.lr_scheduler import StepLR try: import torch.cuda cuda_available = torch.cuda.is_available() except (ImportError, AttributeError): cuda_available = False # ====== GPU训练 ====== if cuda_available: device = torch.device("cuda") print(f"使用设备:{device} - {torch.cuda.get_device_name(0)}") train_kwargs = {'batch_size': 64, 'shuffle': True} test_kwargs = {'batch_size': 1000, 'shuffle': False} train_loader = torch.utils.data.DataLoader(dataset1, **train_kwargs) test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs) model = Net().to(device) optimizer = optim.Adadelta(model.parameters(), lr=1.0) scheduler = StepLR(optimizer, step_size=1, gamma=0.7) for epoch in range(1, 4): train(model, device, train_loader, optimizer, epoch) test(model, device, test_loader) scheduler.step() torch.save(model.state_dict(), "mnist_gpu.pt") print("GPU训练完成,模型已保存为 mnist_gpu.pt") else: print("当前环境无GPU,跳过GPU训练")预期输出:
使用设备:cuda - Tesla V100S-PCIE-32GB Train Epoch: 1 | Loss: 0.1968 | Accuracy: 56419/60000 (94%) Test | Average loss: 0.0542 | Accuracy: 9826/10000 (98%) Train Epoch: 2 | Loss: 0.0759 | Accuracy: 58647/60000 (98%) Test | Average loss: 0.0417 | Accuracy: 9867/10000 (99%) Train Epoch: 3 | Loss: 0.0580 | Accuracy: 59008/60000 (98%) Test | Average loss: 0.0313 | Accuracy: 9891/10000 (99%) GPU训练完成,模型已保存为 mnist_gpu.pt
验证方法:如使用GPU镜像资源,训练完成后应输出“GPU训练完成,模型已保存为mnist_gpu.pt”,3个Epoch的测试准确率应在97%-99%范围内。如果提示“当前环境无GPU”,请检查实例资源规格是否包含GPU。
- NPU训练:以下代码在NPU实例上运行。
迁移要点:与GPU训练对比,仅有三处改动:
- 添加import torch_npu
- torch.cuda→torch.npu
- cuda→npu
import torch import torch.optim as optim from torch.optim.lr_scheduler import StepLR try: import torch_npu # 【改动1】导入NPU适配包 npu_available = torch.npu.is_available() # 【改动2】torch.cuda → torch.npu except (ImportError, AttributeError): npu_available = False # ====== NPU训练 ====== if npu_available: device = torch.device("npu") # 【改动3】cuda → npu print(f"使用设备:{device} - {torch.npu.get_device_name(0)}") train_kwargs = {'batch_size': 64, 'shuffle': True} test_kwargs = {'batch_size': 1000, 'shuffle': False} train_loader = torch.utils.data.DataLoader(dataset1, **train_kwargs) test_loader = torch.utils.data.DataLoader(dataset2, **test_kwargs) model = Net().to(device) optimizer = optim.Adadelta(model.parameters(), lr=1.0) scheduler = StepLR(optimizer, step_size=1, gamma=0.7) for epoch in range(1, 4): train(model, device, train_loader, optimizer, epoch) test(model, device, test_loader) scheduler.step() torch.save(model.state_dict(), "mnist_npu.pt") print("NPU训练完成,模型已保存为 mnist_npu.pt") else: print("当前环境无NPU,跳过NPU训练")预期输出:
使用设备:npu - Ascend910B4 Train Epoch: 1 | Loss: 0.2067 | Accuracy: 56290/60000 (94%) Test | Average loss: 0.0442 | Accuracy: 9844/10000 (98%) Train Epoch: 2 | Loss: 0.0761 | Accuracy: 58734/60000 (98%) Test | Average loss: 0.0344 | Accuracy: 9885/10000 (99%) Train Epoch: 3 | Loss: 0.0544 | Accuracy: 59053/60000 (98%) Test | Average loss: 0.0319 | Accuracy: 9890/10000 (99%) NPU训练完成,模型已保存为 mnist_npu.pt
验证方法:如使用NPU镜像规格,训练完成后应输出“NPU训练完成,模型已保存为mnist_npu.pt”,3个epoch的测试准确率应与GPU训练结果基本一致。如果提示“当前环境无NPU”,请检查镜像是否选择了CANN版本。
- GPU训练:以下代码在GPU实例上运行。
核心Diff对比
+ import torch_npu # 改动1:导入NPU适配包
- if torch.cuda.is_available(): # 改动2:设备检测
+ if torch.npu.is_available():
- device = torch.device("cuda") # 改动3:设备指定
+ device = torch.device("npu") 步骤四:模型推理与跨设备加载
本步骤使用训练好的模型进行推理验证,包括:加载模型权重文件、对测试集图片进行预测并可视化结果。PyTorch权重文件在GPU和NPU间通用,仅需调整map_location参数即可跨设备加载。
- 加载训练好的模型权重文件进行推理。代码会自动检测当前设备类型,并加载对应的模型权重。
PyTorch保存的权重文件(.pt)在GPU和NPU间通用,仅需调整map_location参数。
迁移要点:本案例模型权重文件通用。NPU场景仅map_location需从“cuda:0”改为“npu:0”。除此之外,网络定义、训练逻辑、评估逻辑、数据加载等代码完全一致。
import torch # 自动检测设备并加载对应模型 if torch.cuda.is_available(): device = torch.device("cuda") model_path = "mnist_gpu.pt" map_location = "cuda:0" elif hasattr(torch, 'npu') and torch.npu.is_available(): import torch_npu device = torch.device("npu") model_path = "mnist_npu.pt" map_location = "npu:0" # NPU场景,map_location需从“cuda:0”改为“npu:0” else: device = torch.device("cpu") model_path = "mnist_gpu.pt" map_location = "cpu" model = Net().to(device) model.load_state_dict(torch.load(model_path, map_location=map_location)) model.eval() print(f"模型加载完成,设备:{device}")预期输出:
- NPU:
模型加载完成,设备:npu
- GPU:
模型加载完成,设备:cuda
- NPU:
- 从测试集中选取12张图片,使用加载的模型进行推理预测,展示预测结果与真实标签的对比。
import matplotlib.pyplot as plt num = 12 cols = 4 rows = (num + cols - 1) // cols fig, axes = plt.subplots(rows, cols, figsize=(15, 6)) model.eval() with torch.no_grad(): for i in range(num): image, label = dataset2[i] output = model(image.unsqueeze(0).to(device)) pred = output.argmax(dim=1).item() ax = axes[i // cols, i % cols] ax.imshow(image.squeeze(), cmap='gray') color = 'green' if pred == label else 'red' ax.set_title(f'L:{label} P:{pred}', color=color, fontsize=10) ax.axis('off') plt.tight_layout() plt.show()预期输出:

预测结果图中绿色标题表示预测正确,红色表示预测错误。
步骤五:设备监控
训练和推理过程中,可通过设备监控命令查看NPU或GPU的算力利用率、显存使用量等,帮助判断训练是否正常运行。GPU使用nvidia-smi命令,NPU使用npu-smi info命令,两者的核心监控指标对照如下。
- GPU监控
在GPU实例上运行以下命令nvidia-smi,查看GPU使用率、显存使用量等。
import torch if torch.cuda.is_available(): !nvidia-smi else: print("当前环境无GPU,跳过nvidia-smi")预期输出:
Wed Jul 29 11:50:13 2026 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 470.57.02 Driver Version: 470.57.02 CUDA Version: 11.4 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |===============================+======================+======================| | 0 xxx... On | 00000000:00:0D.0 Off | 0 | | N/A 35C P0 37W / 250W | 2925MiB / 32510MiB | 0% Default | | | | N/A | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=============================================================================| +-----------------------------------------------------------------------------+
- NPU监控
在NPU实例上运行以下命令npu-smi info,查看NPU使用率、显存使用量等。其中AICore(%) 是NPU的算力利用率,等同于GPU的GPU-Util;HBM-Usage(MB) 是显存使用量,等同于GPU的Memory-Usage。
import torch if hasattr(torch, 'npu') and torch.npu.is_available(): !npu-smi info else: print("当前环境无NPU,跳过npu-smi info")预期输出:
+------------------------------------------------------------------------------------------------+ | npu-smi 25.5.1 Version: 25.5.1 | +---------------------------+---------------+----------------------------------------------------+ | NPU Name | Health | Power(W) Temp(C) Hugepages-Usage(page)| | Chip | Bus-Id | AICore(%) Memory-Usage(MB) HBM-Usage(MB) | +===========================+===============+====================================================+ | 0 xxx | OK | 87.5 42 0 / 0 | | 0 | 0000:C1:00.0 | 0 0 / 0 4822 / 32768 | +===========================+===============+====================================================+ +---------------------------+---------------+----------------------------------------------------+ | NPU Chip | Process id | Process name | Process memory(MB) | +===========================+===============+====================================================+ | 0 0 | 3180 | python | 1999 | +===========================+===============+====================================================+
| 指标 | GPU (nvidia-smi) | NPU (npu-smi info) |
|---|---|---|
| 算力利用率 | GPU-Util | AICore(%) |
| 显存使用 | Memory-Usage | HBM-Usage(MB) |
| 设备温度 | Temp | Temp(C) |
| 功耗 | Pwr | Power(W) |
实时监控(持续刷新)
如果需要持续监控,可执行以下命令。
- GPU:
watch -n 1 nvidia-smi(每1秒刷新)
- NPU:
watch -n 1 npu-smi info(每1秒刷新)
常见问题
- 运行NPU训练代码时提示当前环境无NPU,如何排查?
- Notebook实例的资源规格是否选择了NPU类型。
- 镜像是否选择了包含CANN的aarch64架构镜像。
- 实例是否已成功启动并分配到NPU资源。
- GPU训练保存的模型权重能否直接在NPU上加载?
可以。PyTorch权重文件与设备无关,仅需调整map_location参数即可。部分场景需先将权重通过map_location=cpu加载到CPU,再转换至NPU。
更多迁移问题排查,请参见GPU业务迁移至昇腾训练推理。
相关文档
| 文档名称 | 说明 |
|---|---|
| 完整的GPU到NPU迁移指南,涵盖更多场景和进阶配置。 | |
| 昇腾PyTorch适配包的API参考和使用说明。 | |
| Notebook实例的创建、配置和管理方法。 | |
| 各资源规格的计费标准和费用估算。 |