文档首页/ 魔坊(ModelArts)模型训推平台/ 快速入门/ GPU迁移到NPU:手写数字识别
更新时间:2026-08-03 GMT+08:00
分享

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环境。

表1 GPU与NPU API对照表

功能

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实例

  1. 登录ModelArts管理控制台,在左侧导航栏按需选择以下操作。
    • 新版控制台:选择模型开发与训练 > Notebook,进入“Notebook”页面。
    • 旧版控制台:选择开发空间 > Notebook,进入“Notebook”页面。
  2. “Notebook”页面的“操作”列,单击“接入环境”,在“接入方式”对话框的“WebIDE”页签,单击“JupyterLab 接入”右侧的“接入”
  3. 进入JupyterLab页面后,自动打开ModelArts Launcher页面。在“ModelArts Launcher”页面的“Notebook”区域,单击PyTorch,创建一个新的PyTorch Notebook。
    图1 打开PyTorch

步骤二:环境验证

在开始迁移实践前,先验证当前运行环境是否可用。确认设备类型和计算能力正常后,再进行后续的代码迁移。

  1. 设备检测。
    执行以下命令,自动检测当前运行环境是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
  2. 矩阵运算验证。

    通过矩阵乘法验证设备计算能力。以下两个单元格分别对应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])。

步骤三:MNIST手写数字识别

本步骤完成MNIST手写数字识别的完整训练流程,包括:网络模型定义、数据准备与加载、训练与评估函数定义、GPU/NPU训练。其中仅训练部分的代码存在GPU与NPU差异,其余代码在两种环境下完全一致。

  1. 网络模型定义。

    网络模型定义与设备无关,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("网络模型定义完成")

    预期输出:

    网络模型定义完成
  2. 数据准备。
    下载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
  3. 加载数据集。使用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

    如果数据加载失败,请检查数据文件是否下载完整。

  4. 训练与评估函数。定义训练函数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("训练与评估函数定义完成")

    预期输出:

    训练与评估函数定义完成
  5. 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训练对比,仅有三处改动:

      1. 添加import torch_npu
      2. torch.cuda→torch.npu
      3. 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版本。

核心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参数即可跨设备加载。

  1. 加载训练好的模型权重文件进行推理。代码会自动检测当前设备类型,并加载对应的模型权重。

    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
  2. 从测试集中选取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                    |
    +===========================+===============+====================================================+
表2 GPU与NPU监控指标对照

指标

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,如何排查?

    请依次检查:

    1. Notebook实例的资源规格是否选择了NPU类型。
    2. 镜像是否选择了包含CANN的aarch64架构镜像。
    3. 实例是否已成功启动并分配到NPU资源。
  • GPU训练保存的模型权重能否直接在NPU上加载?

    可以。PyTorch权重文件与设备无关,仅需调整map_location参数即可。部分场景需先将权重通过map_location=cpu加载到CPU,再转换至NPU。

更多迁移问题排查,请参见GPU业务迁移至昇腾训练推理

相关文档

文档名称

说明

GPU业务迁移至昇腾训练推理

完整的GPU到NPU迁移指南,涵盖更多场景和进阶配置。

torch_npu官方文档

昇腾PyTorch适配包的API参考和使用说明。

ModelArts Notebook使用指南

Notebook实例的创建、配置和管理方法。

ModelArts计费说明

各资源规格的计费标准和费用估算。

相关文档