© 2023 yanghn. All rights reserved. Powered by Obsidian
5.6 GPU
要点
一些免费的 gpu
查看是否安装 GPU 和 CUDA:
!nvidia-smi
Wed Sep 20 08:41:47 2023
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 470.103.01 Driver Version: 470.103.01 CUDA Version: 11.4 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla T4 On | 00000000:00:07.0 Off | 0 |
| N/A 42C P0 27W / 70W | 506MiB / 15109MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
+-----------------------------------------------------------------------------+
可以看到有一块 GPU, 型号是 Tesla T4,内存是 16G
1. 计算设备
默认情况下,张量是在内存中创建的,然后使用 CPU 计算它。
# 查询 GPU 个数
torch.cuda.device_count() # 1
可以取 GPU、CPU 地址存储为 torch.device
对象,方便后续张量、网络指定存储地址(默认是 CPU ), 注意 cuda:0
和 cuda
是等价的
device = torch.device('cuda:0')
注意
这个操作本身并不会触发任何与硬件交互的操作。换句话说,这只是创建了一个指向特定 CUDA 设备的标识符,但并没有实际去检查该设备是否存在。
device = torch.device('cuda:10') # 这行代码不会报错
x = torch.tensor([1.0, 2.0])
x = x.to(device) # 这行代码会报错,因为系统上没有名为'cuda:10'的设备
2. 张量与 GPU
# 查询张量所在设备
x = torch.tensor([1, 2, 3])
x.device
device(type='cpu') # 默认在CPU
无论何时我们要对多个项进行操作,它们都必须在同一个设备上。例如,如果我们对两个张量求和,我们需要确保两个张量都位于同一个 device 上,否则框架将不知道在哪里存储结果,甚至不知道在哪里执行计算。
X = torch.ones(2, 3, device=torch.device('cuda'))
Y = torch.rand(2, 3, device=torch.device('cpu'))
X + Y # 会报错,原因不在一个 device 上
利用 .cuda()
方法在另一个 GPU 创建同样的张量
Z = Y.cuda(0) # 在第 0 块 GPU 上创建同样的 Y
X + Z # 可以运算
Z.cuda(0) is Z # True 在本身 device 上不会创建副本,而是直接返回本身(性能考虑)
Pytorch 不允许不在同一 device 的张量做运算,因为对于数据在 cpu 和 gpu 之间迁移非常耗时,如果有一层在 cpu,其他都在 gpu,学习过程中数据得来回搬迁,非常耗时
注意
与下一小节的 net.to(device)
不同,net.to(device)
直接就把网络的参数搬到 device 上了, X.to(device)
实际上是返回一个新对象,一般用 X = X.to(device)
把 X
搬到新设备上
3. 神经网络与 GPU
神经网络所在的设备指的是网络的参数所在的设备
net = nn.Sequential(nn.Linear(3, 1))
net = net.to(device=torch.device('cuda:0')) # .to 方法移到 cuda0 上
不像张量有 .device
方法,这些子模块或参数有可能分布在不同的设备上(虽然这种情况并不常见),要查看模型所在设备,可以用:next(model.parameters()).device
,执行这段代码总是返回网络第一层 weight 所在的设备