本地 GPU 学习实验
假设电脑是 Windows 11 + NVIDIA 独立显卡,推荐采用:
Windows NVIDIA 驱动
↓
WSL2 + Ubuntu
↓
CUDA / PyTorch
↓
Docker GPU 容器
↓
NVML GPU 监控
↓
Prometheus + Grafana
↓
单节点 Kubernetes GPU 实验
WSL2 可以让 Linux CUDA 程序使用 Windows 主机的 NVIDIA GPU,因此非常适合学习 Linux、CUDA、容器和云原生 GPU 运维。(NVIDIA Docs)
一、先检查硬件和驱动
在 Windows PowerShell 中运行:
nvidia-smi
正常情况下会看到:
NVIDIA-SMI xxx.xx
Driver Version: xxx.xx
CUDA Version: xx.x
GPU Name
GPU Utilization
Memory Usage
Temperature
Processes
这里需要理解一个重点:
nvidia-smi 显示的 CUDA Version
代表当前驱动最高支持的 CUDA 版本,不等于你已经安装了 CUDA Toolkit。
再检查显卡型号:
nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv
例如可能输出:
name, memory.total [MiB], driver_version
NVIDIA GeForce RTX 3050 Laptop GPU, 4096 MiB, 580.xx
只要 nvidia-smi 可以正常工作,就可以继续。
二、安装 WSL2 和 Ubuntu
使用管理员 PowerShell:
wsl --install -d Ubuntu
安装完成后重启电脑。
查看 WSL 状态:
wsl --status
查看发行版:
wsl -l -v
应该看到:
NAME STATE VERSION
Ubuntu Running 2
如果 Ubuntu 不是 WSL2:
wsl --set-version Ubuntu 2
更新 WSL:
wsl --update
进入 Ubuntu:
wsl
然后在 Ubuntu 中检查 GPU:
nvidia-smi
如果 Windows 和 WSL 中都能看到显卡,说明这条调用链已经打通:
Ubuntu 程序
↓
WSL2 GPU 接口
↓
Windows NVIDIA 驱动
↓
物理 GPU
不要在 WSL2 里安装 Linux NVIDIA 显卡驱动。 WSL 使用的是 Windows 主机驱动提供的 GPU 能力;在 WSL 内重复安装 Linux 驱动容易破坏环境。NVIDIA 官方流程也是先安装支持 WSL 的 Windows 驱动,再安装 WSL2 和 Linux 开发环境。(NVIDIA Docs)
三、准备 Python 环境
在 Ubuntu 中执行:
sudo apt update
sudo apt install -y python3 python3-pip python3-venv git build-essential
建立独立虚拟环境:
python3 -m venv ~/venvs/nvidia-lab
source ~/venvs/nvidia-lab/bin/activate
升级基础工具:
python -m pip install --upgrade pip setuptools wheel
以后进入实验环境都执行:
source ~/venvs/nvidia-lab/bin/activate
退出环境:
deactivate
四、先使用 PyTorch 体验 GPU
对于初学者,建议先装 PyTorch,而不是立即安装完整 CUDA Toolkit。
原因是:
直接学习 CUDA C++
难度较高
PyTorch 调用 CUDA
几分钟就能看到效果
请使用 PyTorch 官方安装选择器生成与你当前系统匹配的命令。通常需要选择:
OS: Linux
Package: Pip
Language: Python
Compute Platform: CUDA
安装后运行:
python
输入:
import torch
print("PyTorch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
print("CUDA runtime:", torch.version.cuda)
if torch.cuda.is_available():
print("GPU:", torch.cuda.get_device_name(0))
print("GPU count:", torch.cuda.device_count())
期望看到:
CUDA available: True
GPU: NVIDIA GeForce RTX ...
做一次矩阵计算
创建文件:
nano gpu_test.py
写入:
import time
import torch
def benchmark(device: str, size: int = 5000) -> float:
a = torch.randn(size, size, device=device)
b = torch.randn(size, size, device=device)
if device == "cuda":
torch.cuda.synchronize()
start = time.perf_counter()
_ = a @ b
if device == "cuda":
torch.cuda.synchronize()
return time.perf_counter() - start
def main() -> None:
print(f"PyTorch version: {torch.__version__}")
print(f"CUDA available: {torch.cuda.is_available()}")
cpu_time = benchmark("cpu", size=2000)
print(f"CPU time: {cpu_time:.4f} seconds")
if torch.cuda.is_available():
print(f"GPU: {torch.cuda.get_device_name(0)}")
gpu_time = benchmark("cuda", size=2000)
print(f"GPU time: {gpu_time:.4f} seconds")
print(f"Approximate speedup: {cpu_time / gpu_time:.2f}x")
if __name__ == "__main__":
main()
运行:
python gpu_test.py
第一次 GPU 运算可能较慢,因为会发生 CUDA 初始化。更准确的测试应该预热后运行多次,不过这个实验足以验证 PyTorch 是否真正使用了 GPU。
运行程序的同时,另开一个终端执行:
watch -n 1 nvidia-smi
你会看到:
-
GPU 利用率上升
-
显存被占用
-
Python 进程出现
-
功耗和温度变化
这就是最简单的 GPU 可观测性实验。
五、使用 NVML 编写监控程序
安装 Python NVML 库:
pip install nvidia-ml-py
创建:
nano gpu_monitor.py
写入:
import time
from pynvml import (
NVMLError,
nvmlDeviceGetCount,
nvmlDeviceGetHandleByIndex,
nvmlDeviceGetMemoryInfo,
nvmlDeviceGetName,
nvmlDeviceGetPowerUsage,
nvmlDeviceGetTemperature,
nvmlDeviceGetUtilizationRates,
nvmlInit,
nvmlShutdown,
NVML_TEMPERATURE_GPU,
)
def mib(value: int) -> float:
return value / 1024 / 1024
def main() -> None:
try:
nvmlInit()
count = nvmlDeviceGetCount()
while True:
print("-" * 70)
for index in range(count):
handle = nvmlDeviceGetHandleByIndex(index)
name = nvmlDeviceGetName(handle)
utilization = nvmlDeviceGetUtilizationRates(handle)
memory = nvmlDeviceGetMemoryInfo(handle)
temperature = nvmlDeviceGetTemperature(
handle,
NVML_TEMPERATURE_GPU,
)
try:
power_watts = nvmlDeviceGetPowerUsage(handle) / 1000
power_text = f"{power_watts:.1f} W"
except NVMLError:
power_text = "unsupported"
print(f"GPU {index}: {name}")
print(f" GPU utilization: {utilization.gpu}%")
print(f" Memory utilization: {utilization.memory}%")
print(
f" VRAM: {mib(memory.used):.0f} / "
f"{mib(memory.total):.0f} MiB"
)
print(f" Temperature: {temperature}°C")
print(f" Power: {power_text}")
time.sleep(2)
except KeyboardInterrupt:
print("\nMonitor stopped.")
except NVMLError as exc:
print(f"NVML error: {exc}")
finally:
try:
nvmlShutdown()
except NVMLError:
pass
if __name__ == "__main__":
main()
运行:
python gpu_monitor.py
同时运行前面的矩阵计算程序:
python gpu_test.py
你就能观察到:
Python 计算任务
↓
PyTorch
↓
CUDA
↓
NVIDIA Driver
↓
GPU
与此同时:
GPU
↓
Driver
↓
NVML
↓
gpu_monitor.py
这个实验非常适合以后扩展成 AIOps 项目,例如:
-
GPU 温度超过阈值时报警
-
显存使用超过 90% 时通知
-
检测 GPU 空闲资源
-
收集 GPU 使用趋势
-
关联 GPU 进程与用户
六、尝试 CUDA C++ 编程
只有在需要使用以下工具时,才需要安装 CUDA Toolkit:
nvcc
CUDA headers
CUDA samples
Nsight 工具
自行编译 CUDA 程序
CUDA Toolkit 包含编译器、运行时、加速库、调试和性能分析工具。(NVIDIA Developer)
安装完成后检查:
nvcc --version
创建:
nano vector_add.cu
写入:
#include <cuda_runtime.h>
#include <cstdlib>
#include <iostream>
#include <vector>
#define CUDA_CHECK(call) \
do { \
cudaError_t error = (call); \
if (error != cudaSuccess) { \
std::cerr << "CUDA error: " \
<< cudaGetErrorString(error) \
<< " at line " << __LINE__ << std::endl; \
std::exit(EXIT_FAILURE); \
} \
} while (0)
__global__ void vector_add(
const float* a,
const float* b,
float* result,
int size
) {
int index = blockIdx.x * blockDim.x + threadIdx.x;
if (index < size) {
result[index] = a[index] + b[index];
}
}
int main() {
constexpr int size = 1'000'000;
const std::size_t bytes = size * sizeof(float);
std::vector<float> host_a(size, 1.0F);
std::vector<float> host_b(size, 2.0F);
std::vector<float> host_result(size);
float* device_a = nullptr;
float* device_b = nullptr;
float* device_result = nullptr;
CUDA_CHECK(cudaMalloc(&device_a, bytes));
CUDA_CHECK(cudaMalloc(&device_b, bytes));
CUDA_CHECK(cudaMalloc(&device_result, bytes));
CUDA_CHECK(cudaMemcpy(
device_a,
host_a.data(),
bytes,
cudaMemcpyHostToDevice
));
CUDA_CHECK(cudaMemcpy(
device_b,
host_b.data(),
bytes,
cudaMemcpyHostToDevice
));
constexpr int threads = 256;
const int blocks = (size + threads - 1) / threads;
vector_add<<<blocks, threads>>>(
device_a,
device_b,
device_result,
size
);
CUDA_CHECK(cudaGetLastError());
CUDA_CHECK(cudaDeviceSynchronize());
CUDA_CHECK(cudaMemcpy(
host_result.data(),
device_result,
bytes,
cudaMemcpyDeviceToHost
));
std::cout << "Result[0]: " << host_result[0] << '\n';
std::cout << "Result[last]: " << host_result.back() << '\n';
CUDA_CHECK(cudaFree(device_a));
CUDA_CHECK(cudaFree(device_b));
CUDA_CHECK(cudaFree(device_result));
return 0;
}
编译:
nvcc vector_add.cu -o vector_add
运行:
./vector_add
结果应为:
Result[0]: 3
Result[last]: 3
这时你亲自走完了:
CUDA C++ 源代码
↓
nvcc 编译
↓
CPU Host Code + GPU Kernel
↓
CUDA Runtime
↓
NVIDIA Driver
↓
GPU SM 执行线程
七、尝试 GPU Docker 容器
NVIDIA Container Toolkit 负责让 Docker 或其他容器运行时把 GPU 设备及相关库暴露给容器。(NVIDIA Docs)
在 Windows + WSL2 环境下,比较简单的方式是:
-
安装 Docker Desktop。
-
启用 WSL2 后端。
-
打开 Ubuntu 的 WSL Integration。
-
在 Ubuntu 中执行 Docker 命令。
先检查:
docker version
然后运行一个 CUDA 容器:
docker run --rm --gpus all \
nvidia/cuda:12.9.1-base-ubuntu24.04 \
nvidia-smi
容器标签会随时间变化;若这个标签不存在,请换成 NVIDIA CUDA 镜像仓库当前存在的 base-ubuntu 标签。
正常时,容器里也能看到显卡:
Docker Container
↓
NVIDIA Container Runtime
↓
WSL GPU 接口
↓
Windows NVIDIA Driver
↓
GPU
进一步运行 PyTorch 容器:
docker run --rm -it --gpus all \
pytorch/pytorch:latest \
python -c "import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))"
学习容器时重点观察:
docker run --rm --gpus all ...
其中:
--gpus all
表示将可用 GPU 暴露给这个容器。
八、尝试 DCGM Exporter
DCGM Exporter 通过 HTTP /metrics 暴露 GPU 指标,Prometheus 可以直接抓取这些指标。(NVIDIA Docs)
可以先尝试容器:
docker run --rm --gpus all \
--cap-add SYS_ADMIN \
-p 9400:9400 \
nvcr.io/nvidia/k8s/dcgm-exporter:latest
另开一个终端:
curl http://localhost:9400/metrics
可能看到:
DCGM_FI_DEV_GPU_UTIL
DCGM_FI_DEV_FB_USED
DCGM_FI_DEV_FB_FREE
DCGM_FI_DEV_GPU_TEMP
DCGM_FI_DEV_POWER_USAGE
不过需要注意:
-
DCGM 的核心用途是数据中心 GPU 管理。
-
GeForce 支持的指标和诊断能力可能少于数据中心 GPU。
-
WSL2 也存在功能限制。
-
某些容器权限和性能指标可能不可用。
DCGM 官方支持部分非数据中心 NVIDIA GPU,但不同产品可用功能并不完全相同。(NVIDIA Docs)
因此,笔记本上 DCGM Exporter 跑不通时,不要把它理解成显卡损坏。先用以下组合学习监控即可:
nvidia-smi
NVML Python
Prometheus 自定义 Exporter
Grafana
九、自己写一个 Prometheus GPU Exporter
这比直接部署 DCGM Exporter更适合作为第一个 AIOps 项目。
安装:
pip install prometheus-client nvidia-ml-py
创建:
nano nvml_exporter.py
写入:
import time
from prometheus_client import Gauge, start_http_server
from pynvml import (
NVMLError,
NVML_TEMPERATURE_GPU,
nvmlDeviceGetCount,
nvmlDeviceGetHandleByIndex,
nvmlDeviceGetMemoryInfo,
nvmlDeviceGetName,
nvmlDeviceGetTemperature,
nvmlDeviceGetUtilizationRates,
nvmlInit,
nvmlShutdown,
)
GPU_UTILIZATION = Gauge(
"nvidia_gpu_utilization_percent",
"GPU utilization percentage",
["gpu", "name"],
)
GPU_MEMORY_USED = Gauge(
"nvidia_gpu_memory_used_bytes",
"GPU framebuffer memory currently used",
["gpu", "name"],
)
GPU_MEMORY_TOTAL = Gauge(
"nvidia_gpu_memory_total_bytes",
"Total GPU framebuffer memory",
["gpu", "name"],
)
GPU_TEMPERATURE = Gauge(
"nvidia_gpu_temperature_celsius",
"GPU temperature in Celsius",
["gpu", "name"],
)
def collect_metrics() -> None:
count = nvmlDeviceGetCount()
for index in range(count):
handle = nvmlDeviceGetHandleByIndex(index)
name = nvmlDeviceGetName(handle)
labels = {
"gpu": str(index),
"name": name,
}
utilization = nvmlDeviceGetUtilizationRates(handle)
memory = nvmlDeviceGetMemoryInfo(handle)
temperature = nvmlDeviceGetTemperature(
handle,
NVML_TEMPERATURE_GPU,
)
GPU_UTILIZATION.labels(**labels).set(utilization.gpu)
GPU_MEMORY_USED.labels(**labels).set(memory.used)
GPU_MEMORY_TOTAL.labels(**labels).set(memory.total)
GPU_TEMPERATURE.labels(**labels).set(temperature)
def main() -> None:
try:
nvmlInit()
start_http_server(9401)
print("NVML exporter listening on http://localhost:9401/metrics")
while True:
collect_metrics()
time.sleep(2)
except KeyboardInterrupt:
print("\nExporter stopped.")
except NVMLError as exc:
print(f"NVML error: {exc}")
finally:
try:
nvmlShutdown()
except NVMLError:
pass
if __name__ == "__main__":
main()
运行:
python nvml_exporter.py
查看:
curl http://localhost:9401/metrics
这样你就已经实现了一个迷你版:
NVML
↓
Python Exporter
↓
HTTP /metrics
↓
Prometheus
↓
Grafana
这个项目对学习 Python、GPU 运维和 Prometheus 很有价值。
十、尝试 Kubernetes GPU
笔记本上建议把 Kubernetes 放在最后,因为它是最容易被环境问题绊住的一层。
需要理解 Kubernetes 本身不会直接操作 GPU,而是通过厂商提供的 Device Plugin 将 GPU 注册为可调度资源。(Kubernetes)
理想链路是:
Kubernetes
↓
NVIDIA Device Plugin
↓
NVIDIA Container Toolkit
↓
NVIDIA Driver
↓
GPU
Pod 通常这样申请 GPU:
apiVersion: v1
kind: Pod
metadata:
name: pytorch-gpu-test
spec:
restartPolicy: Never
containers:
- name: pytorch
image: pytorch/pytorch:latest
command:
- python
- -c
- |
import torch
print("CUDA available:", torch.cuda.is_available())
if torch.cuda.is_available():
print("GPU:", torch.cuda.get_device_name(0))
resources:
limits:
nvidia.com/gpu: 1
保存为:
gpu-pod.yaml
部署:
kubectl apply -f gpu-pod.yaml
kubectl logs pytorch-gpu-test
查看节点是否注册 GPU:
kubectl describe node
查找:
Capacity:
nvidia.com/gpu: 1
Allocatable:
nvidia.com/gpu: 1
不过在 Windows + WSL2 + Docker Desktop Kubernetes 中,GPU Device Plugin 的兼容性和配置通常不如原生 Linux稳定。因此更推荐两种方式:
第一种:笔记本安装原生 Ubuntu,使用 k3s 或 kubeadm
第二种:先在 WSL2 学 Docker GPU,Kubernetes GPU 放到云服务器实验
NVIDIA GPU Operator 可以自动部署驱动、Container Toolkit、Device Plugin、DCGM Exporter 和 MIG Manager,但它更适合标准 Linux GPU 节点,而不是作为笔记本上的第一个实验。(NVIDIA Docs)
哪些功能可以在消费级笔记本上学习
| 技术 | 笔记本可行性 | 建议 |
|---|---|---|
nvidia-smi | 很高 | 马上尝试 |
| PyTorch CUDA | 很高 | 第一阶段重点 |
| NVML Python | 很高 | 运维方向重点 |
| CUDA C++ | 高 | 第二阶段学习 |
| GPU Docker | 高 | 容器方向重点 |
| Prometheus + Grafana | 很高 | AIOps 项目重点 |
| DCGM Exporter | 中等 | 能跑就学,失败不必死磕 |
| TensorRT | 中高 | 推理阶段学习 |
| Triton Server | 中高 | 可以部署小模型 |
| vLLM | 取决于显存 | 小显存限制明显 |
| Kubernetes Device Plugin | 中低 | 原生 Linux 更合适 |
| NCCL 多卡通信 | 低 | 单 GPU 无法完整实验 |
| MIG | 不可行 | 通常需要支持 MIG 的数据中心 GPU |
| NVLink/NVSwitch | 不可行 | 需要服务器硬件 |
| Fabric Manager | 不可行 | 需要 NVSwitch 平台 |
推荐的学习顺序
不要一次安装所有东西。按下面六个实验推进:
实验 1:Windows 和 WSL 中运行 nvidia-smi
实验 2:PyTorch 完成 GPU 矩阵计算
实验 3:用 NVML 编写 GPU 监控脚本
实验 4:运行 CUDA 或 PyTorch GPU 容器
实验 5:自制 Exporter + Prometheus + Grafana
实验 6:在原生 Linux 或云服务器实验 Kubernetes GPU
当前最应该先完成前三项。完成后,你已经能够清楚理解:
应用如何使用 GPU
CUDA 与驱动是什么关系
监控程序如何读取 GPU 指标
显存、利用率、功耗和进程如何变化
而 MIG、NVLink、NVSwitch、Fabric Manager 和多机 NCCL 不适合在普通笔记本上强行模拟,后面租用一台数据中心 GPU 云服务器集中体验,会比折腾本地虚拟化有效得多。
