C++老兵从零手写GPT(一):RTX 5080 环境踩坑,我装错了两次 PyTorch
系列说明:我是一名普本计科毕业生,做了 5 年 C++ 类 CAD 的 3D 开发。Python 只停留在"看得懂、没怎么写过"的阶段。AI 正在改变软件行业,我不想只做 API 调用者,于是决定用家里的 RTX 5080,从零手写一个 GPT。这是系列第一篇,不讲大道理,先记录环境踩坑。
一、我的环境
- 系统:Windows
- GPU:NVIDIA GeForce RTX 5080,16GB 显存,Blackwell 架构,计算能力
sm_120 - 内存:64GB
- Python:3.12.7
- 驱动:621.01,CUDA UMD 13.5
目标很简单:让 PyTorch 真正识别这块 5080,并能跑通一次 GPU 矩阵乘法。不是"能 import 就算成功",而是确认真实计算落在 GPU 上。
二、先看显卡状态
PowerShell 里执行:
powershell
nvidia-smi
输出关键信息:
text
NVIDIA-SMI 621.01 KMD Version: 621.01 CUDA UMD Version: 13.5
GPU Name: NVIDIA GeForce RTX 5080
Memory-Usage: 1853MiB / 16303MiB
16GB 显存,驱动很新,硬件没问题。注意这里显示的是驱动支持的 CUDA UMD 版本,不代表要装系统级 CUDA Toolkit。PyTorch 的 pip 包自带运行时,不需要单独装 CUDA Toolkit。
三、建虚拟环境
Python 项目先隔离环境,避免污染系统 Python:
powershell
mkdir D:\llm-from-scratch
cd D:\llm-from-scratch
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m venv .venv 的含义是:运行 Python 标准库里的 venv 模块,在当前目录创建名为 .venv 的隔离环境。它会在 .venv\Scripts 下生成独立的 python.exe、pip.exe,并在 .venv\Lib\site-packages 下放这个项目自己的包。用 C++ 类比,相当于给项目建一个独立的 build/ 目录,依赖都装里面,不碰系统。
踩坑一:PowerShell 禁止运行脚本
第一次激活就报错:
text
.\.venv\Scripts\Activate.ps1 : 无法加载文件 ...\Activate.ps1,因为在此系统上禁止运行脚本。
这是 PowerShell 的执行策略,不是虚拟环境坏了。解决方式:
powershell
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
输入 Y 确认。RemoteSigned 的意思是本地脚本可以运行,从互联网下载的脚本仍需签名,安全性和便利性平衡。也可以临时绕过:
powershell
Set-ExecutionPolicy -Scope Process Bypass
只对当前窗口生效,关掉即失效。
激活成功后,提示符前面会出现 (.venv)。用这条确认当前解释器:
powershell
python -c "import sys; print(sys.executable)"
输出必须是:
text
D:\llm-from-scratch\.venv\Scripts\python.exe
四、踩坑二:装成了 CPU 版 PyTorch
升级 pip 后开始安装 PyTorch。第一次用了阿里云镜像:
powershell
pip install torch torchvision torchaudio -f https://mirrors.aliyun.com/pytorch-wheels/cu128/
装完跑验证脚本,结果:
text
torch version: 2.15.0+cpu
cuda version: None
cuda available: False
CUDA 不可用
问题很清楚:安装到了 +cpu 构建。这个版本不包含任何 NVIDIA GPU 支持代码,cuda available 必然是 False。版本号新不代表能用 GPU,关键看构建变体。
你的 RTX 5080 是 Blackwell 架构,计算能力为 sm_120。PyTorch 自 2.7.0 稳定版起正式支持 Blackwell,但必须使用 CUDA 12.8 或更高版本的构建。安装 CPU 版或旧 CUDA 版,要么 cuda available: False,要么报错 sm_120 is not compatible。
五、换源重装 cu128
卸载 CPU 版,换南京大学镜像装 CUDA 12.8 构建:
powershell
pip uninstall torch torchvision torchaudio -y
pip install torch torchvision torchaudio --index-url https://mirrors.nju.edu.cn/pytorch/whl/cu128
安装成功:
text
Successfully installed torch-2.11.0+cu128 torchaudio-2.11.0+cu128 torchvision-0.26.0+cu128
注意 +cu128 后缀。这就是构建变体的标记,带它才是 CUDA 12.8 版本。
六、验证脚本
新建 check_gpu.py:
python
import torch
print("torch version:", torch.__version__)
print("cuda version:", torch.version.cuda)
print("cuda available:", torch.cuda.is_available())
if torch.cuda.is_available():
print("device:", torch.cuda.get_device_name(0))
print("capability:", torch.cuda.get_device_capability(0))
x = torch.randn(1024, 1024, device="cuda")
y = x @ x
torch.cuda.synchronize()
print("gpu matmul ok, mean:", y.mean().item())
else:
print("CUDA 不可用,把完整输出贴出来")
运行:
powershell
.\.venv\Scripts\python.exe .\check_gpu.py
输出:
text
torch version: 2.11.0+cu128
cuda version: 12.8
cuda available: True
device: NVIDIA GeForce RTX 5080
capability: (12, 0)
gpu matmul ok, mean: -0.04079888015985489
逐行解读:
2.11.0+cu128:CUDA 12.8 构建,不是 CPU 版;cuda available: True:GPU 可用;capability: (12, 0):sm_120,Blackwell 被正确识别;gpu matmul ok:1024×1024 矩阵乘法真的在 GPU 上跑完了,不只是"能 import"。
mean 是负数完全正常,随机矩阵相乘元素有正有负,均值接近 0 说明计算没问题。
七、跑通第一个训练循环
环境通了,跑一个最小线性回归,确认训练循环五步能工作。新建 day1_linear.py:
python
import torch
import torch.nn as nn
torch.manual_seed(0)
device = "cuda" if torch.cuda.is_available() else "cpu"
x = torch.randn(1000, 1, device=device)
y = 3 * x + 2 + 0.1 * torch.randn(1000, 1, device=device)
model = nn.Linear(1, 1).to(device)
loss_fn = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
for step in range(200):
pred = model(x)
loss = loss_fn(pred, y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
if step % 20 == 0:
print(step, loss.item())
print("weight:", model.weight.item(), "bias:", model.bias.item())
运行:
powershell
.\.venv\Scripts\python.exe .\day1_linear.py
输出:
text
0 10.576257705688477
20 0.012022092938423157
40 0.009533579461276531
60 0.009532982483506203
...
weight: 3.0003602504730225 bias: 2.0045979022979736
weight 收敛到 3.00036,bias 收敛到 2.0046,目标就是 3 和 2,结果正确。
loss 为什么停在 0.00953 不再降?因为数据里加了 0.1 * randn 噪声,方差是 0.01。模型无法拟合随机噪声,MSE 的理论下限就在 0.01 附近。0.00953 已经贴着下限,说明参数学到了真实关系,剩下的误差全是噪声。这不是没收敛好,是正常现象。
八、用 C++ 视角理解 PyTorch
作为 C++ 开发者,我用类比理解这几个概念:
- Tensor :带形状、能上 GPU 的多维数组,像强化版
std::vector/数组。GPT 里输入输出都是[batch, seq_len, hidden_dim]形状。 - autograd:前向时自动记录计算图,反向时按链式法则自动算梯度。你只写前向,不写反向。底层是 C++ 的计算图引擎,Python 只是接口。
- nn.Module :模型基类,像带参数注册机制的抽象基类。
nn.Linear、nn.Embedding都是它的子类。 - Optimizer :持有参数引用,根据
.grad更新参数。
训练循环五步,后面手写 GPT 也是这个骨架:
text
forward → loss → zero_grad → backward → step
九、今天的验收清单
-
nvidia-smi正常显示 RTX 5080 - 虚拟环境激活后
sys.executable指向.venv - PyTorch 版本带
+cu128,不是+cpu -
cuda available: True,capability: (12, 0) - GPU 矩阵乘法真实执行
- 线性回归 loss 收敛,weight≈3,bias≈2
十、踩坑总结
- PowerShell 默认禁止脚本 :用
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned解决。 - 镜像源可能给 CPU 版 :
2.15.0+cpu看起来版本新,但没有 CUDA 支持。装完必须看版本后缀是不是+cu128。 - Blackwell 必须 CUDA 12.8+ :RTX 5080 是
sm_120,旧 CUDA 构建不包含对应 kernel。 - 不要只看
is_available():还要看capability和真实矩阵乘法,才能确认计算链路通了。 - loss 停在噪声下限是正常的:数据带噪声时,MSE 不会降到 0。
十一、下一篇
下一篇不碰环境,做 PyTorch 最小必要:Python 函数/类/模块,Tensor 形状操作,reshape/view/transpose/广播,为后面 Attention 的形状推导打基础。
本文为个人学习记录,代码仅供学习参考,不构成任何课程替代。完整代码后续会同步到代码仓库。