GPU#

首先,确保至少安装了一个NVIDIA GPU。

  • 首先下载安装好NVIDIA的显卡驱动

  • 然后需要确保NVIDIA的CUDA的版本是NVIDIA驱动支持的范围内。

  • 接着需要安装torch的GPU版本!pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

如果这些装好了,在PyCharm里可以识别,但是Jupyter Notebook仍然不能识别GPU,那么可以使用下面方法

pip install ipykernel
python -m ipykernel install --name python3_ai  # python3_ai为环境

如果要删除这个环境的话使用下面命令

jupyter kernelspec remove python3_ai

当这些准备工作完成,就可以使用nvidia-smi命令来查看显卡信息。

如何没有显卡可以去kaggle.com上嫖30小时,而且有两块卡用

!nvidia-smi
Thu Jul 25 02:39:45 2024       
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.90.07              Driver Version: 550.90.07      CUDA Version: 12.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                       Off |   00000000:00:04.0 Off |                    0 |
| N/A   57C    P8             10W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
|   1  Tesla T4                       Off |   00000000:00:05.0 Off |                    0 |
| N/A   60C    P8             10W /   70W |       1MiB /  15360MiB |      0%      Default |
|                                         |                        |                  N/A |
+-----------------------------------------+------------------------+----------------------+
                                                                                         
+-----------------------------------------------------------------------------------------+
| Processes:                                                                              |
|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |
|        ID   ID                                                               Usage      |
|=========================================================================================|
|  No running processes found                                                             |
+-----------------------------------------------------------------------------------------+

要运行此部分中的程序,至少需要两个GPU

计算设备#

我们可以指定用于存储和计算的设备,如CPU和GPU。 默认情况下,张量是在内存中创建的,然后使用CPU计算它。

在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:0cuda是等价的。

import torch
from torch import nn

torch.device('cpu'),torch.device('cuda'),torch.device('cuda:1')
(device(type='cpu'), device(type='cuda'), device(type='cuda', index=1))

判断GPU是否准备就绪,常见的后端调用有下面这些

torch.backends.cpu

torch.backends.cuda

torch.backends.cudnn

torch.backends.mha

torch.backends.mps

torch.backends.mkl

torch.backends.mkldnn

torch.backends.nnpack

torch.backends.openmp

torch.backends.opt_einsum

torch.backends.xeon
#判断MAC的GPU是否准备就绪
torch.backends.mps.is_available()
False

我们可以查询可用gpu的数量。

#N卡的用,由于我们没有所以这边是0
print(torch.cuda.is_available())
print(torch.cuda.device_count())
True
2

现在我们定义了两个方便的函数,这两个函数允许我们在不存在所需所有GPU的情况下运行代码

def try_gpu(i=0):  #@save
    """如果存在,则返回gpu(i),否则返回cpu()"""
    if torch.cuda.device_count() >= i + 1:
        return torch.device(f'cuda:{i}')
    return torch.device('cpu')

def try_all_gpus():  #@save
    """返回所有可用的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()
(device(type='cuda', index=0),
 device(type='cpu'),
 [device(type='cuda', index=0), device(type='cuda', index=1)])

张量与GPU#

我们可以查询张量所在的设备。 默认情况下,张量是在CPU上创建的。

x = torch.tensor([1, 2, 3])
x.device
device(type='cpu')

需要注意的是,无论何时我们要对多个项进行操作, 它们都必须在同一个设备上。 例如,如果我们对两个张量求和, 我们需要确保两个张量都位于同一个设备上, 否则框架将不知道在哪里存储结果,甚至不知道在哪里执行计算。

存储在GPU上#

有几种方法可以在GPU上存储张量。 例如,我们可以在创建张量时指定存储设备。接 下来,我们在第一个gpu上创建张量变量X。 在GPU上创建的张量只消耗这个GPU的显存。 我们可以使用nvidia-smi命令查看显存使用情况。 一般来说,我们需要确保不创建超过GPU显存限制的数据。

X = torch.ones(2, 3, device=try_gpu())
X
tensor([[1., 1., 1.],
        [1., 1., 1.]], device='cuda:0')

假设我们至少有两个GPU,下面的代码将在第二个GPU上创建一个随机张量。

如果我们没有显卡的话,那么就会把数据移动到CPU中

Y = torch.rand(2, 3, device=try_gpu(1))
Y
tensor([[1.0488e-01, 9.0968e-01, 5.3550e-01],
        [6.8839e-01, 1.0349e-01, 2.6808e-04]], device='cuda:1')

复制#

如果我们要计算X + Y,我们需要决定在哪里执行这个操作。 我们可以将X传输到第二个GPU并在那里执行操作。 不要简单地X加上Y,因为这会导致异常, 运行时引擎不知道该怎么做:它在同一设备上找不到数据会导致失败。 由于Y位于第二个GPU上,所以我们需要将X移到那里, 然后才能执行相加运算。

Z = X.cuda(1)
print(X)
print(Z)
tensor([[1., 1., 1.],
        [1., 1., 1.]], device='cuda:0')
tensor([[1., 1., 1.],
        [1., 1., 1.]], device='cuda:1')

现在数据在同一个GPU上(ZY都在),我们可以将它们相加。

Y + Z
tensor([[1.1049, 1.9097, 1.5355],
        [1.6884, 1.1035, 1.0003]], device='cuda:1')

假设变量Z已经存在于第二个GPU上。 如果我们还是调用Z.cuda(1)会发生什么? 它将返回Z,而不会复制并分配新内存。

Z.cuda(1) is Z
True

神经网络与GPU#

类似地,神经网络模型可以指定设备。 下面的代码将模型参数放在GPU上。

net = nn.Sequential(nn.Linear(3, 1))
net = net.to(device=try_gpu())

在接下来的几章中, 我们将看到更多关于如何在GPU上运行模型的例子, 因为它们将变得更加计算密集。

当输入为GPU上的张量时,模型将在同一GPU上计算结果。

net(X)
tensor([[0.4161],
        [0.4161]], device='cuda:0', grad_fn=<AddmmBackward0>)

让我们确认模型参数存储在同一个GPU上。

net[0].weight.data.device
device(type='cuda', index=0)

总之,只要所有的数据和参数都在同一个设备上, 我们就可以有效地学习模型。