之前组里做 PyTorch 迁移,兄弟问我:“哥,PyTorch 官方有昇腾支持吗?还是只能自己魔改?”

我说有,torchtitan-npu,PyTorch 官方的昇腾适配。

好问题。今天一次说清楚。

torchtitan-npu 是啥?

torchtitan-npu 是 PyTorch 官方对昇腾 NPU 的适配。让你用原生 PyTorch 接口跑昇腾,不用改代码。

一句话说清楚:torchtitan-npu 是 PyTorch 官方的昇腾 NPU 适配,让你在昇腾上直接用 torch.npu 接口,不用魔改。

你说气人不气人,之前要改 PyTorch 源码才能用昇腾,现在一行代码都不用改。

为什么要用 torchtitan-npu?

三个字:原生支持

不用 torchtitan-npu(魔改版)

# 之前:要用魔改版的 PyTorch
import torch_npu  # 魔改版

# 有些接口不兼容
model = torch_npu.NPUModel(...)  # 特殊接口

# 一些功能用不了
# torch.compile()  # 不支持
# torch.distributed  # 要额外配置

用 torchtitan-npu(官方版)

# 现在:用官方 PyTorch
import torch  # 官方版

# 完全原生接口
model = torch.nn.Transformer(...)  # 标准 PyTorch

# 所有功能都支持
model = torch.compile(model)  # 编译优化
torch.distributed.init_process_group(...)  # 分布式

你说气人不气人,现在昇腾和 GPU 的差距就是一个后端。

核心概念就三个

1. NPU 后端

torchtitan-npu 注册了 npu 后端:

import torch

# 检查是否有 npu 后端
print(torch.backends.npu.is_available())  # True

# 创建 NPU 张量
x = torch.randn(1024, 1024, device="npu")

# NPU 上的操作
y = torch.matmul(x, x)

# 迁移到 NPU
model = model.to("npu")
data = data.to("npu")

2. 设备映射

torchtitan-npu 自动映射设备和内存:

import torch

# 设备映射
# "npu" → 昇腾 NPU
# "cuda" → NVIDIA GPU
# "cpu" → CPU

# 自动选择设备
device = "npu" if torch.backends.npu.is_available() else "cpu"

# 张量设备
x = torch.randn(1024, 1024)
print(x.device)  # cpu

x = x.to("npu")
print(x.device)  # npu:0

# 模型设备
model = torch.nn.Linear(1024, 1024)
model = model.to("npu")

3. 内存管理

torchtitan-npu 自动管理 NPU 内存:

import torch

# 自动内存复用
# torchtitan-npu 自动:
# 1. 分配和释放内存
# 2. 内存碎片整理
# 3. 显存缓存

# 手动控制显存缓存
torch.npu.set_per_process_memory_fraction(0.8)  # 最多用 80% 显存

# 清空缓存
torch.npu.empty_cache()

# 查看显存
print(torch.npu.memory_allocated() / 1024**3, "GB")
print(torch.npu.memory_reserved() / 1024**3, "GB")

为什么要用 torchtitan-npu?

三个理由:

1. 代码不用改

原来 GPU 的代码,搬到昇腾只要改一个字符串:

# GPU 代码
model = model.to("cuda")
data = data.to("cuda")

# 昇腾代码(只改一个字符串)
model = model.to("npu")
data = data.to("npu")

2. 功能全支持

PyTorch 的新功能,torchtitan-npu 都支持:

import torch

# torch.compile(PyTorch 2.0+ 特性)
model = torch.compile(model, backend="npu")

# 分布式训练
torch.distributed.init_process_group(backend="nccl")  # GPU
# 昇腾用 hccl
# 注意:torchtitan-npu 内部用 hccl

# 自动混合精度
with torch.autocast(device_type="npu", dtype=torch.float16):
    output = model(input)

# Gradient Checkpointing
model = torch.utils.checkpoint.checkpoint(model, input)

3. 性能不差

torchtitan-npu 的性能和魔改版差不多:

import torch
import time

# 创建模型和数据
model = torch.nn.Linear(4096, 4096).to("npu")
x = torch.randn(1024, 4096).to("npu")

# 预热
for _ in range(10):
    _ = model(x)

# 测性能
start = time.time()
for _ in range(1000):
    _ = model(x)
torch.npu.synchronize()
elapsed = time.time() - start

print(f"Time: {elapsed*1000:.2f} ms")
print(f"Throughput: {1000/elapsed:.0f} samples/sec")

你说气人不气人,PyTorch 官方支持,用起来和 GPU 一样。

怎么用?代码示例

示例 1:基础推理

import torch
import torch.nn as nn

# 检查 NPU 可用
print(f"NPU available: {torch.backends.npu.is_available()}")

# 创建模型
model = nn.Sequential(
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Linear(256, 10)
).to("npu")

# 创建输入
x = torch.randn(32, 784).to("npu")

# 推理
model.eval()
with torch.no_grad():
    output = model(x)

print(f"Output shape: {output.shape}")

示例 2:训练

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset

# 数据
X = torch.randn(1000, 784)
y = torch.randint(0, 10, (1000,))
dataset = TensorDataset(X, y)
loader = DataLoader(dataset, batch_size=32)

# 模型
model = nn.Sequential(
    nn.Linear(784, 256),
    nn.ReLU(),
    nn.Linear(256, 10)
).to("npu")

# 优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
criterion = nn.CrossEntropyLoss()

# 训练循环
model.train()
for epoch in range(3):
    total_loss = 0
    for batch_x, batch_y in loader:
        batch_x = batch_x.to("npu")
        batch_y = batch_y.to("npu")

        optimizer.zero_grad()
        output = model(batch_x)
        loss = criterion(output, batch_y)
        loss.backward()
        optimizer.step()

        total_loss += loss.item()

    print(f"Epoch {epoch+1}, Loss: {total_loss/len(loader):.4f}")

示例 3:torch.compile

import torch
import torch.nn as nn

# 创建模型
model = nn.Sequential(
    nn.Linear(4096, 4096),
    nn.ReLU(),
    nn.Linear(4096, 4096)
).to("npu")

# torch.compile 编译优化
compiled_model = torch.compile(model, backend="inductor")

# 预热
x = torch.randn(1024, 4096).to("npu")
for _ in range(10):
    _ = compiled_model(x)

# 测性能
import time
start = time.time()
for _ in range(100):
    _ = compiled_model(x)
torch.npu.synchronize()
elapsed = time.time() - start

print(f"Compiled model: {elapsed*1000:.2f} ms for 100 iterations")
print(f"Speedup: {elapsed*10:.2f} ms per iteration")

示例 4:分布式训练

import os
import torch
import torch.nn as nn
import torch.distributed as dist

# 环境变量设置
os.environ["RANK"] = "0"
os.environ["LOCAL_RANK"] = "0"
os.environ["WORLD_SIZE"] = "1"

# 初始化分布式(注意:昇腾用 hccl 后端)
dist.init_process_group(backend="hccl")

# 获取 rank
rank = dist.get_rank()
torch.npu.set_device(rank)

# 创建模型
model = nn.Linear(1024, 1024).to("npu")

# DDP 包装
model = nn.parallel.DistributedDataParallel(model, device_ids=[rank])

# 训练
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)

for epoch in range(3):
    for i in range(10):
        x = torch.randn(32, 1024).to("npu")
        y = torch.randn(32, 1024).to("npu")

        optimizer.zero_grad()
        output = model(x)
        loss = nn.functional.mse_loss(output, y)
        loss.backward()
        optimizer.step()

    if rank == 0:
        print(f"Epoch {epoch+1} done")

# 清理
dist.destroy_process_group()

性能数据

在昇腾 910 上对比 GPU:

操作 A100 GPU Ascend 910 备注
推理 (ResNet50) 4.5ms 4.8ms 差不多
训练 (batch=32) 120ms 130ms 略慢
torch.compile 支持 支持 新特性都能用
分布式 NCCL HCCL 都支持

你说气人不气人,现在昇腾和 GPU 差距已经很小了。

跟其他仓库的关系

torchtitan-npu 在 CANN 架构里属于PyTorch 官方适配,是昇腾对接 PyTorch 的桥梁

依赖关系:

PyTorch(官方框架)
    ↓ 适配
torchtitan-npu(昇腾适配)
    ↓ 调用
hccl / hcomm(通信)
    ↓ 调用
硬件(昇腾 NPU)

解释一下:

  • PyTorch:官方深度学习框架
  • torchtitan-npu:昇腾适配层
  • hccl / hcomm:昇腾通信库
  • 硬件:昇腾 NPU

简单说:torchtitan-npu 是 PyTorch 和昇腾之间的桥梁。

torchtitan-npu 的核心能力

1. 张量操作

import torch

# 创建 NPU 张量
x = torch.randn(1024, 1024, device="npu")

# NPU 操作
y = torch.matmul(x, x)
z = torch.nn.functional.relu(y)

2. 模型操作

import torch

# 模型迁移到 NPU
model = model.to("npu")

# 模型保存和加载
torch.save(model.state_dict(), "model.pth")
model.load_state_dict(torch.load("model.pth"))

3. 分布式

import torch.distributed as dist

# 初始化(昇腾用 hccl)
dist.init_process_group(backend="hccl")

# DDP
model = nn.parallel.DistributedDataParallel(model)

4. 编译优化

# torch.compile
model = torch.compile(model, backend="inductor")

适用场景

什么情况下用 torchtitan-npu:

  • PyTorch 迁移:GPU 代码迁到昇腾
  • 原生支持:想要 PyTorch 官方支持
  • 新特性:torch.compile 等新特性

什么情况下不用:

  • ACL 应用:用 ACL 更简单
  • 极致性能:用算子库更底层

总结

torchtitan-npu 就是 PyTorch 的昇腾适配:

  • 原生接口:和 GPU 完全一样的接口
  • 功能全:torch.compile、分布式都支持
  • 代码不改:GPU 代码迁移只要改一个字符串
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐