动手学人工智能-深度学习计算6-高效利用GPU加速计算

452 阅读5分钟

随着深度学习的快速发展,计算资源的需求不断增加。传统的CPU逐渐无法满足训练深度神经网络所需的巨大计算量,因此,GPU(图形处理单元)成为了深度学习研究中的重要工具。在本文中,我们将深入探讨GPU的基本概念、如何利用单个或多个GPU加速深度学习任务,以及在实践中如何高效使用GPU。

1. GPU的性能发展

过去20年,计算能力的飞速增长使得GPU成为了深度学习的核心硬件之一。从2000年以来,GPU的性能每十年增长了约1000倍。这种显著的提升,使得GPU能够在复杂的计算任务(例如深度神经网络训练)中展现出极其强大的优势。利用GPU的并行计算能力,可以大幅度加速深度学习模型的训练过程。

2. 如何使用GPU进行计算

在进行深度学习任务时,首先需要确保计算机上安装了NVIDIA GPU,并且正确安装了NVIDIA驱动和CUDA工具包。安装完成后,您可以使用 nvidia-smi 命令查看显卡的状态和性能。

例如,使用命令行查看GPU信息时,输出可能类似如下:

屏幕截图 2024-12-23 143907.png

输出结果显示GPU的使用情况、显存占用等信息,帮助我们监控GPU的状态。

3. PyTorch中的GPU设备管理

在PyTorch中,每个张量都有一个设备(device),也可以称作环境(context)。默认情况下,所有的计算操作都发生在CPU上,但我们可以通过指定设备将计算任务转移到GPU上。常见的设备表示方式包括:

  • torch.device('cpu') 表示使用CPU。
  • torch.device('cuda') 表示使用GPU(通常是GPU 0)。
  • torch.device('cuda:1') 表示使用第2块GPU(如果系统中有多个GPU)。

在实际操作中,可以通过以下代码检查当前可用的设备:

import torch

torch.device('cpu'), torch.device('cuda'), torch.device('cuda:1')

输出结果表示不同设备的信息:

屏幕截图 2024-12-23 144619.png

通过 torch.cuda.device_count()可以查询可用的GPU数量。

torch.cuda.device_count()

返回的数字表示当前系统中可用的GPU数量。

屏幕截图 2024-12-23 144740.png

3.1 自动选择设备

为了简化代码,可以使用一些辅助函数自动选择GPU。如果系统中没有可用的GPU,程序会自动使用CPU。下面是一个简单的示例:

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'), ]

这样做可以确保在没有GPU时程序不会出错,并且可以灵活地选择不同的设备进行计算。

屏幕截图 2024-12-23 145427.png

4. 张量与GPU

4.1 创建和存储在GPU上的张量

在PyTorch中,张量默认是在CPU上创建的。但是,我们可以在创建张量时指定它们存储的位置。例如,使用以下代码可以在GPU上创建一个张量:

X = torch.ones(2, 3, device=torch.device('cuda'))

输出结果:

屏幕截图 2024-12-23 150134.png

这表示 X 是存储在GPU上的张量。

4.2 张量的设备查询

可以通过 tensor.device 查询一个张量当前所在的设备。例如:

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

屏幕截图 2024-12-23 150424.png

当操作涉及多个张量时,需要保证它们都位于相同的设备上。否则,PyTorch会抛出错误。例如,如果尝试对两个不同设备上的张量进行运算,代码会失败。

屏幕截图 2024-12-23 150621.png

4.3 张量数据传输

如果两个张量位于不同的设备上,我们需要显式地将其中一个张量移动到另一个设备。例如,假设x位于CPU,而y位于GPU 0,要执行相加操作,我们必须首先将 x 移到GPU 0:

屏幕截图 2024-12-23 150902.png

在这里,我们通过cuda(0)将张量x移动到GPU 0,然后在同一个设备上执行加法操作。

5. 神经网络与GPU

5.1 将模型参数迁移到GPU

类似于张量,我们也可以将神经网络的模型参数迁移到GPU上。在PyTorch中,可以通过 .to(device) 方法将模型转移到指定的设备上:

import torch
from torch import nn

net = nn.Sequential(nn.Linear(3, 1))
X = torch.randn((2, 3))
output = net(X)
print(output.device)

X = X.cuda()
net = net.to(device=torch.device('cuda'))
output = net(X)
print(output.device)

当输入张量也存储在GPU上时,模型将自动使用GPU进行计算。例如,如果X位于GPU上:

屏幕截图 2024-12-23 151625.png

数据和模型必须在同一设备上,才能进行计算,否则会报错。

屏幕截图 2024-12-23 151815.png

6. 小结

  • 设备管理:我们可以通过 torch.device 指定使用CPU或GPU进行计算。默认情况下,PyTorch在CPU上进行计算,但我们可以轻松地将计算转移到GPU上加速任务。

  • 数据移动的开销:尽管GPU计算速度非常快,但设备间的数据传输往往成为性能瓶颈。因此,尽量减少设备间的数据传输,并确保数据和计算在同一设备上执行,是提高计算效率的关键。

  • 神经网络与GPU:将神经网络的模型参数和输入数据都放在同一GPU上进行计算,可以显著提高训练效率。在训练深度学习模型时,确保数据和模型都位于GPU上,是提升训练速度的有效方式。