🚀 3、快速上手:第一个MindSpore训练脚本
说实话,很多初学者拿到一个新框架,最怕的就是“跑不起来”。我刚开始接触MindSpore时也踩过几个坑,但一旦把第一个脚本跑通,后面就顺了。这一章咱们直接动手——写一个极简的训练脚本,在昇腾设备上跑起来,然后看看日志和性能数据。你跟着我走一遍,半小时内就能看到loss下降。
📝 3.1 写一个能跑的脚本
我个人习惯先用一个最简单的全连接网络做验证。下面这个例子用 MindSpore 实现了一个两层的分类器,数据集就用随机生成的 fake data。你直接复制就能跑。
import numpy as np
import mindspore as ms
from mindspore import nn, Tensor, context
from mindspore.ops import operations as P
# 设置运行环境:昇腾 NPU
context.set_context(mode=context.GRAPH_MODE, device_target="Ascend")
# 定义一个简单的网络
class SimpleNet(nn.Cell):
def __init__(self):
super().__init__()
self.fc1 = nn.Dense(32, 64)
self.fc2 = nn.Dense(64, 10)
self.relu = nn.ReLU()
def construct(self, x):
x = self.relu(self.fc1(x))
return self.fc2(x)
net = SimpleNet()
loss_fn = nn.SoftmaxCrossEntropyWithLogits()
optimizer = nn.SGD(net.trainable_params(), learning_rate=0.01)
# 伪造数据
data = Tensor(np.random.randn(128, 32).astype(np.float32))
label = Tensor(np.random.randint(0, 10, (128,)).astype(np.int32))
# 训练一步
def forward_fn(data, label):
logits = net(data)
loss = loss_fn(logits, label)
return loss
grad_fn = ms.value_and_grad(forward_fn, None, optimizer.parameters)
for step in range(20):
loss, grads = grad_fn(data, label)
optimizer(grads)
print(f"step {step}, loss: {loss.asnumpy():.4f}")
mode=context.GRAPH_MODE 打开,昇腾在静态图下性能最好。如果你遇到算子报错,可以先切到 PYNATIVE_MODE 调试,我经常这么干。
⚙️ 3.2 在昇腾上运行
脚本写好了,怎么在昇腾设备上跑?其实很简单。只要你的环境按照第2章搭好了,直接 python train.py 就行。MindSpore 会自动检测到昇腾芯片。
但我遇到过一种情况:明明插了卡,却报错“No device found”。后来发现是环境变量 ASCEND_DEVICE_ID 没设。你可以用下面命令确认:
# 查看可用昇腾设备
npu-smi info
# 或者
ascend-dmi -i
# 指定设备(可选)
export ASCEND_DEVICE_ID=0
python train.py
step 0, loss: 2.4123
step 1, loss: 2.3101
step 2, loss: 2.1987
…… loss 逐渐下降,说明网络在正常学习。
嗯,这里要注意:如果你用 PyNative 模式,昇腾也能跑,但图模式才是它的完全体。我建议你一开始就用 GRAPH_MODE,后面调优时再对比。
📊 3.3 查看训练日志与性能数据
光看 loss 打印还不够,咱们得学会“看透”训练过程。MindSpore 提供了 Callback 机制,可以轻松记录时间、吞吐、loss 曲线。
下面我加了一个 LossMonitor 和 TimeMonitor,你跑完就能看到每个 step 的耗时:
from mindspore.train.callback import LossMonitor, TimeMonitor
from mindspore import Model
model = Model(net, loss_fn=loss_fn, optimizer=optimizer)
model.train(epoch=1, train_dataset=dataset, callbacks=[LossMonitor(), TimeMonitor()])
输出会变成这样:
epoch: 1 step: 0, loss: 2.312, per_step_time: 23.45 ms
epoch: 1 step: 1, loss: 2.201, per_step_time: 21.02 ms
...
你想想看,如果 per_step_time 突然飙到 100ms,那肯定有瓶颈。我一般会先看数据加载是不是成了短板。
📈 3.4 性能数据进阶:profiler 初探
想更深入地看算子耗时、内存占用?MindSpore 自带 Profiler,一键导出性能数据。我个人觉得这是调优最实用的工具。
from mindspore.profiler import Profiler
profiler = Profiler(output_path="./profiler_data")
# 训练代码...
model.train(epoch=1, train_dataset=dataset)
profiler.analyse()
跑完后在 ./profiler_data 下会生成 ascend_*.json 文件。你可以用 MindSpore Insight 可视化界面打开,或者直接看文本摘要。我曾经靠这个发现一个算子被重复编译了三次,优化后训练速度提升了 40%。
🧩 3.5 一张表总结:快速上手三板斧
| 步骤 | 核心操作 | 常用命令/代码 |
|---|---|---|
| 1. 写脚本 | 定义网络、loss、优化器 | nn.Cell + construct |
| 2. 昇腾运行 | 设置 device_target="Ascend" | context.set_context |
| 3. 看日志 | 使用 Callback 或 print | LossMonitor, TimeMonitor |
| 4. 性能分析 | Profiler 采集 | Profiler(output_path=...) |
说白了,快速上手就是这三步:写一个能收敛的脚本,在昇腾上跑通,然后通过日志和数据确认它在高效运行。你只要跑通一次,后面所有章节都会建立在这个基础上。