查看显卡信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Tue Jun 1 15:40:45 2021 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 418.67 Driver Version: 418.67 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 Tesla V100-SXM2... Off | 00000000:00:1B.0 Off | 0 | | N/A 56C P0 55W / 300W | 8124MiB / 16130MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 1 Tesla V100-SXM2... Off | 00000000:00:1C.0 Off | 0 | | N/A 43C P0 51W / 300W | 4252MiB / 16130MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 2 Tesla V100-SXM2... Off | 00000000:00:1D.0 Off | 0 | | N/A 41C P0 40W / 300W | 11MiB / 16130MiB | 0% Default | +-------------------------------+----------------------+----------------------+ | 3 Tesla V100-SXM2... Off | 00000000:00:1E.0 Off | 0 | | N/A 62C P0 62W / 300W | 1582MiB / 16130MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | 0 2277 C ...buntu/miniconda3/envs/d2l-en/bin/python 3289MiB | | 0 127232 C ...buntu/miniconda3/envs/d2l-en/bin/python 1389MiB | +-----------------------------------------------------------------------------+
计算设备
在 PyTorch 中,CPU 和GPU 可以用torch.device('cpu')
和torch.device('cuda')
表示。 应该注意的是,cpu
设备意味着所有物理 CPU 和内存,这意味着 PyTorch 的计算将尝试使用所有 CPU 核心。然而,gpu
设备只代表一个卡和相应的显存。如果有多个 GPU,使用torch.device(f'cuda:{i}')
来表示第 i 块 GPU(i 从 0 开始)。另外,cuda:0
和cuda
是等价的。
1 2 3 4 import torchfrom torch import nntorch.device('cpu' ), torch.cuda.device('cuda' ), torch.cuda.device('cuda:1' )
1 2 3 (device(type='cpu'), <torch.cuda.device at 0x7f723468cdc0>, <torch.cuda.device at 0x7f7234655310>)
查询可用 GPU 的数量:
1 torch.cuda.device_count()
这两个函数允许在请求的 GPU 不存在的情况下运行代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 def try_gpu (i=0 ): """如果存在,则返回gpu(i),否则返回cpu()。""" if torch.cuda.device_count() >= i + 1 : return torch.device(f'cuda:{i} ' ) return torch.device('cpu' ) def try_all_gpus (): """返回所有可用的GPU,如果没有GPU,则返回[cpu(),]。""" devices = [ torch.device(f'cuda:{i} ' ) for i in range (torch.cuda.device_count())] return devices if devices else [torch.device('cpu' )] try_gpu(), try_gpu(10 ), try_all_gpus()
1 2 3 (device(type='cuda', index=0), device(type='cpu'), [device(type='cuda', index=0), device(type='cuda', index=1)])
张量与 GPU
查询张量所在的设备:
1 2 x = torch.tensor([1 , 2 , 3 ]) x.device
无论何时我们要对多个项进行操作,它们都必须在同一个设备上。
存储在 GPU 上
1 2 X = torch.ones(2 , 3 , device=try_gpu()) X
1 2 tensor([[1., 1., 1.], [1., 1., 1.]], device='cuda:0')
第二个 GPU 上创建一个随机张量:
1 2 Y = torch.rand(2 , 3 , device=try_gpu(1 )) Y
1 2 tensor([[0.9333, 0.8735, 0.7784], [0.3453, 0.5509, 0.3475]], device='cuda:1')
复制
要计算X + Y
,需要决定在哪里执行这个操作。
1 2 3 Z = X.cuda(1 ) print(X) print(Z)
1 2 3 4 tensor([[1., 1., 1.], [1., 1., 1.]], device='cuda:0') tensor([[1., 1., 1.], [1., 1., 1.]], device='cuda:1')
1 2 tensor([[1.9333, 1.8735, 1.7784], [1.3453, 1.5509, 1.3475]], device='cuda:1')
假设变量Z
已经存在于第二个 GPU 上,如果还是调用Z.cuda(1)
将返回Z
,而不会复制并分配新内存。
神经网络与 GPU
神经网络模型可以指定设备,如下将模型参数放在 GPU 上:
1 2 3 4 net = nn.Sequential(nn.Linear(3 , 1 )) net = net.to(device=try_gpu()) net(X)
1 2 tensor([[-0.8412], [-0.8412]], device='cuda:0', grad_fn=<AddmmBackward>)
确认模型参数存储在同一个 GPU 上:
1 net[0 ].weight.data.device
1 device(type='cuda', index=0)
总结
我们可以指定用于存储和计算的设备,例如 CPU 或 GPU。默认情况下,数据在主内存中创建,然后使用 CPU 进行计算。
深度学习框架要求计算的所有输入数据都在同一设备上,无论是 CPU 还是 GPU。
不经意地移动数据可能会显著降低性能。一个典型的错误如下:计算 GPU 上每个小批量的损失,并在命令行中将其报告给用户(或将其记录在NumPy ndarray中)时,将触发全局解释器锁,从而使所有 GPU 阻塞。最好是为 GPU 内部的日志分配内存,并且只移动较大的日志。