一键导入
code-migration
Migrate CUDA code to Ascend NPU code. Use when implementing PyTorch to NPU migration, replacing CUDA APIs with torch_npu equivalents.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Migrate CUDA code to Ascend NPU code. Use when implementing PyTorch to NPU migration, replacing CUDA APIs with torch_npu equivalents.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Analyze PyTorch model architecture for Ascend NPU compatibility. Use when examining model structure, CUDA usage, distributed training patterns, and identifying migration requirements.
Analyze computation-intensive operators and performance for Ascend NPU. Use when examining model operations, performance bottlenecks, and CANN operator library support.
Analyze Python package dependencies for Ascend NPU compatibility. Use when examining requirements.txt, setup.py, environment files, and checking for CUDA-dependent packages.
Analyze memory access patterns and optimization opportunities for Ascend NPU. Use when examining data loading, host-device transfers, mixed precision training, and memory efficiency.
Migrate PyTorch model training code for Ascend NPU. Use when converting training loops, optimizers, data loading, and distributed training from CUDA to NPU.
| name | code-migration |
| description | Migrate CUDA code to Ascend NPU code. Use when implementing PyTorch to NPU migration, replacing CUDA APIs with torch_npu equivalents. |
You are implementing CUDA to NPU code migration. This skill provides guidance for:
Invoke this skill when:
# Old (CUDA)
device = torch.device('cuda')
model = model.cuda()
tensor = tensor.to('cuda')
tensor = tensor.cuda()
# New (NPU)
device = torch.device('npu')
model = model.npu() # or model.to('npu')
tensor = tensor.to('npu')
tensor = tensor.npu()
# CUDA → NPU
torch.cuda.device_count() → torch.npu.device_count()
torch.cuda.current_device() → torch.npu.current_device()
torch.cuda.get_device_name(i) → torch.npu.get_device_name(i)
torch.cuda.set_device(i) → torch.npu.set_device(i)
torch.cuda.current_stream() → torch.npu.current_stream()
torch.cuda.Stream() → torch.npu.Stream()
torch.cuda.Event() → torch.npu.Event()
# CUDA → NPU
torch.cuda.empty_cache() → torch.npu.empty_cache()
torch.cuda.memory_allocated() → torch.npu.memory_allocated()
torch.cuda.max_memory_allocated() → torch.npu.max_memory_allocated()
torch.cuda.memory_reserved() → torch.npu.memory_reserved()
torch.cuda.ipc_collect() → torch.npu.ipc_collect()
torch.cuda.synchronize() → torch.npu.synchronize()
# CUDA
from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()
with autocast():
output = model(input)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
# NPU
from torch_npu import amp
scaler = amp.GradScaler()
with amp.autocast():
output = model(input)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
# CUDA (NCCL backend)
torch.distributed.init_process_group(
backend='nccl',
init_method='env://'
)
model = torch.nn.parallel.DistributedDataParallel(model)
# NPU (HCCL backend)
torch.distributed.init_process_group(
backend='hccl',
init_method='env://'
)
model = torch.nn.parallel.DistributedDataParallel(model)
# Note: torch_npu automatically uses HCCL when on NPU
# Flash Attention → NPU Fusion Attention
# Old
from flash_attn import flash_attn_func
output = flash_attn_func(q, k, v)
# New
import torch_npu
output = torch_npu.npu_fusion_attention(q, k, v)[0]
# Or use PyTorch native (works on NPU)
output = F.scaled_dot_product_attention(q, k, v)
# Before
class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 64, 3)
self.fc = nn.Linear(64, 10)
def forward(self, x):
return self.fc(self.conv1(x).cuda())
# After
class MyModel(nn.Module):
def __init__(self):
super().__init__()
self.conv1 = nn.Conv2d(3, 64, 3)
self.fc = nn.Linear(64, 10)
def forward(self, x):
# Remove explicit .cuda(), rely on automatic data migration
return self.fc(self.conv1(x))
# Before
device = torch.device('cuda')
model = Model().to(device).cuda()
optimizer = torch.optim.Adam(model.parameters())
for epoch in range(epochs):
for batch in dataloader:
inputs, labels = batch
inputs, labels = inputs.cuda(), labels.cuda()
with torch.cuda.amp.autocast():
outputs = model(inputs)
loss = criterion(outputs, labels)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
torch.cuda.empty_cache()
# After
device = torch.device('npu')
model = Model().to(device).npu() # Explicitly place on NPU
optimizer = torch.optim.Adam(model.parameters())
from torch_npu import amp
scaler = amp.GradScaler()
for epoch in range(epochs):
for batch in dataloader:
inputs, labels = batch
# Automatic data migration handles this
# But explicit is also fine
inputs, labels = inputs.to(device), labels.to(device)
with amp.autocast():
outputs = model(inputs)
loss = criterion(outputs, labels)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
torch.npu.empty_cache()
# Before
import torch.distributed as dist
dist.init_process_group(backend='nccl')
local_rank = int(os.environ['LOCAL_RANK'])
torch.cuda.set_device(local_rank)
model = model.to(local_rank)
model = torch.nn.parallel.DistributedDataParallel(
model, device_ids=[local_rank]
)
# After
import torch.distributed as dist
dist.init_process_group(backend='hccl')
local_rank = int(os.environ['LOCAL_RANK'])
torch.npu.set_device(local_rank)
model = model.to(local_rank)
model = torch.nn.parallel.DistributedDataParallel(
model, device_ids=[local_rank]
)
# Environment variables needed:
# export ASCEND_VISIBLE_DEVICES=0,1,2,3
# export HCCL_WHITELIST_DISABLE=1
# Wrong - will fail
import torch
from torch.cuda.amp import autocast # CUDA-specific
# Correct
import torch
import torch_npu # Import torch_npu
from torch_npu import amp # NPU-specific
# Wrong
device = torch.device('cuda:0')
tensor = tensor.to('cuda')
# Correct - use 'npu'
device = torch.device('npu:0')
tensor = tensor.to('npu')
# Or use dynamic device detection
device = torch.device('npu' if torch.npu.is_available() else 'cpu')
# Wrong - still uses NCCL
dist.init_process_group(backend='nccl')
# Correct - use HCCL for NPU
dist.init_process_group(backend='hccl')
# Wrong
if torch.cuda.is_available():
device = torch.device('cuda')
# Correct
if torch.npu.is_available():
device = torch.device('npu')
elif torch.cuda.is_available():
device = torch.device('cuda')
else:
device = torch.device('cpu')
Use automatic data migration when possible
.to('npu') callsEnable mixed precision training
torch_npu.amp.autocastProfile before optimizing
Test on small batches first
Handle NPU unavailability
# Compare NPU vs CPU outputs
model_cpu = Model()
model_npu = Model().to('npu')
model_cpu.load_state_dict(model_npu.cpu().state_dict())
with torch.no_grad():
output_cpu = model_cpu(inputs)
output_npu = model_npu(inputs.to('npu'))
# Check numerical accuracy
assert torch.allclose(output_cpu, output_npu.cpu(), rtol=1e-3, atol=1e-5)
import time
# Benchmark NPU performance
model = Model().to('npu')
inputs = inputs.to('npu')
# Warmup
for _ in range(10):
_ = model(inputs)
# Measure
torch.npu.synchronize()
start = time.time()
for _ in range(100):
_ = model(inputs)
torch.npu.synchronize()
end = time.time()
avg_time = (end - start) / 100
print(f"Average time: {avg_time:.4f}s")
print(f"Throughput: {1/avg_time:.2f} samples/sec")
# Monitor memory usage
print(f"Memory allocated: {torch.npu.memory_allocated() / 1e9:.2f} GB")
print(f"Max memory: {torch.npu.max_memory_allocated() / 1e9:.2f} GB")
# Check for leaks
torch.npu.empty_cache()
Documentation First:
Code Modification:
Read and Edit for code modificationsGrep to find CUDA patternsBash to test migrated codeWhen generating migrated code: