• 深度学习计算 - GPU


    GPU

    !nvidia-smi
    
    • 1
    Fri Sep  9 12:48:41 2022       
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 512.72       Driver Version: 512.72       CUDA Version: 11.6     |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name            TCC/WDDM | Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |                               |                      |               MIG M. |
    |===============================+======================+======================|
    |   0  NVIDIA GeForce ... WDDM  | 00000000:01:00.0 Off |                  N/A |
    | N/A   51C    P8    10W /  N/A |      0MiB /  6144MiB |      0%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
                                                                                   
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在PyTorch中,每个数组都有一个设备(device),我们通常及那个其称为上下文(context)。默认情况下,所有变量和相关的计算都分配给CPU,有时上下文是CPU。当我们跨多个服务器部署作业时,事情会变得更加棘手。通过智能地将数组分配给上下文,我们可以最大限度地减少在设备之间传输数据的时间。例如,当在带有GPU的服务器上训练神经网络时,我们通常希望模型的参数在GPU上

    1 - 计算设备

    我们可以指定用于存储和计算的设备,比如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,另外,cuda:0和cuda是等价的

    import torch
    from torch import nn
    
    torch.device('cpu'),torch.device('cuda'), torch.device('cuda:1')
    
    • 1
    • 2
    • 3
    • 4
    (device(type='cpu'), device(type='cuda'), device(type='cuda', index=1))
    
    • 1

    查看可以GPU数量

    torch.cuda.device_count()
    
    • 1
    1
    
    • 1

    我们定义两个方便的函数,这两个函数允许我们在不存在所需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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    (device(type='cuda', index=0),
     device(type='cpu'),
     [device(type='cuda', index=0)])
    
    • 1
    • 2
    • 3

    2 - 张量与GPU

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

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

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

    存储在GPU上

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

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

    假设你⾄少有两个GPU,下⾯的代码将在第⼆个GPU上创建⼀个随机张量

    Y = torch.rand(2, 3, device=try_gpu(1))
    Y
    
    • 1
    • 2
    tensor([[0.6770, 0.3752, 0.0100],
            [0.4635, 0.7391, 0.4980]])
    
    • 1
    • 2

    复制

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

    旁注

    ⼈们使⽤GPU来进⾏机器学习,因为单个GPU相对运⾏速度快。但是在设备(CPU、GPU和其他机器)之间传输数据⽐计算慢得多。这也使得并⾏化变得更加困难,因为我们必须等待数据被发送(或者接收),然后才能继续进⾏更多的操作

    根据经验,多个⼩操作⽐⼀个⼤操作糟糕得多。此外,⼀次执⾏⼏个操作⽐代码中散布的许多单个操作要好得多(除⾮你确信⾃⼰在做什么)。如果⼀个设备必须等待另⼀个设备才能执⾏其他操作,那么这样的操作可能会阻塞

    最后,当我们打印张量或将张量转换为NumPy格式时,如果数据不在内存中,框架会⾸先将其复制到内存中,这会导致额外的传输开销。更糟糕的是,它现在受制于全局解释器锁,使得⼀切都得等待Python完成

    3 - 神经网络与GPU

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

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

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

    当输⼊为GPU上的张量时,模型将在同⼀GPU上计算结果

    net(X)
    
    • 1
    tensor([[-0.1674],
            [-0.1674]], device='cuda:0', grad_fn=)
    
    • 1
    • 2

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

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

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

    4 - 小结

    • 我们可以指定⽤于存储和计算的设备,例如CPU或GPU。默认情况下,数据在主内存中创建,然后使⽤CPU进⾏计算
    • 深度学习框架要求计算的所有输⼊数据都在同⼀设备上,⽆论是CPU还是GPU
    • 不经意地移动数据可能会显著降低性能。⼀个典型的错误如下:计算GPU上每个⼩批量的损失,并在命令⾏中将其报告给⽤⼾(或将其记录在NumPy ndarray中)时,将触发全局解释器锁,从⽽使所有GPU阻塞。最好是为GPU内部的⽇志分配内存,并且只移动较⼤的⽇志
  • 相关阅读:
    无人机飞控系统硬件设计
    前端性能优化方法与实战01 体系总览:性能优化体系及关键指标设定
    分布式ID生成解决方案——雪花生成算法Golang实现
    前几年外包干了四年,秋招感觉人生就这样了..
    基于x86架构的CentOS7虚拟机通过qemu安装ARM架构OpenEuler虚拟机
    JAVA 时间戳
    CSS 之 table 表格布局
    python+flask计算机毕业设计基于微信小程序的首饰商城系统(程序+开题+论文)
    【C语言】文件操作
    【网络安全专栏目录】--企鹅专栏导航
  • 原文地址:https://blog.csdn.net/mynameisgt/article/details/126798403