《动手学深度学习 Pytorch版》 5.6 GPU

5.6.1 计算设备

python 复制代码
import torch
from torch import nn

torch.device('cpu'), torch.device('cuda:0')  # cuda等价于cuda:0(只有一块显卡没法试别的块号)
复制代码
(device(type='cpu'), device(type='cuda', index=0))
python 复制代码
torch.cuda.device_count()  # 查询可用GPU数量
复制代码
1
python 复制代码
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)])

5.6.2 张量与GPU

python 复制代码
x = torch.tensor([1, 2, 3])
x.device  # 默认情况下张量是存储在CPU上的
复制代码
device(type='cpu')
  1. 存储在GPU上

    可以在创建张量时选择位置

python 复制代码
X = torch.ones(2, 3, device=try_gpu())  # 只有一个GPU也就不试下面那个了
X
复制代码
tensor([[1., 1., 1.],
        [1., 1., 1.]], device='cuda:0')
  1. 复制

    需要执行运算的数据需要在同一块GPU上,如果不在则可以复制过去。

python 复制代码
# Z = X.cuda(1)  # 没显卡没法试
X.cuda(0) is X  # 如果已存在则不会复制
复制代码
True
  1. 旁注

    谨慎复制,并行化的瓶颈在于数据传输而不是运算速度。

5.6.3 神经网络与GPU

python 复制代码
net = nn.Sequential(nn.Linear(3, 1))
net = net.to(device=try_gpu())  # 模型也可以指定位置

net(X)
复制代码
tensor([[0.3092],
        [0.3092]], device='cuda:0', grad_fn=<AddmmBackward0>)
python 复制代码
net[0].weight.data.device #  所需要的数据和参数在同一设备时才可用该设备运算
复制代码
device(type='cuda', index=0)

练习

(1)尝试一个计算量很大的任务,比如大矩阵的乘法,看看CPU和GPU的速度差异。再尝试一个计算量很小的任务呢?

python 复制代码
import time

start_CPU=time.time()
for i in range(1000):
    A = torch.rand(1000, 1000)
    B = torch.rand(1000, 1000)
    C = torch.matmul(A, B)
end_CPU=time.time()

start_GPU=time.time()
for i in range(1000):
    A = torch.rand(1000, 1000, device=try_gpu())
    B = torch.rand(1000, 1000, device=try_gpu())
    C = torch.matmul(A, B)
end_GPU=time.time()

print(f'大计算量任务CPU运算时长: {round((end_CPU - start_CPU)*1000, 2)} ms')
print(f'大计算量任务GPU运算时长: {round((end_GPU - start_GPU)*1000, 2)} ms')

start_CPU=time.time()
A = torch.rand(5, 5)
B = torch.rand(5, 5)
C = torch.matmul(A, B)
end_CPU=time.time()

start_GPU=time.time()
A = torch.rand(5, 5, device=try_gpu())
B = torch.rand(5, 5, device=try_gpu())
C = torch.matmul(A, B)
end_GPU=time.time()

print(f'小计算量任务CPU运算时长: {round((end_CPU - start_CPU) * 1000, 2)} ms')
print(f'小计算量任务CPU运算时长: {round((end_GPU - start_GPU) * 1000, 2)} ms')
复制代码
大计算量任务CPU运算时长: 23190.1 ms
大计算量任务GPU运算时长: 60.0 ms
小计算量任务CPU运算时长: 1.0 ms
小计算量任务GPU运算时长: 0.0 ms

(2)我们应该如何在GPU上读写模型参数?

使用 net.to() 函数迁移模型到 GPU 上即可。


(3)测量计算 1000 个 100*100 矩阵乘法所需的时间,并记录输出矩阵的弗罗贝尼乌斯范数,一次记录一个结果,而不是在GPU上保存日志并进传输最终结果。

python 复制代码
A = torch.rand(100, 100, device=try_gpu())

start = time.time()
for i in range(1000):
    A = torch.mm(A, A)
    B = torch.norm(A)  # 逐个记录
end = time.time()
print(f'逐个记录耗费时间:{round((end - start) * 1000)} ms')

A = torch.rand(100, 100, device=try_gpu())
start = time.time()
for i in range(1000):
    A = torch.mm(A, A)
B = torch.norm(A)  # 最终记录
end = time.time()
print(f'最终记录耗费时间:{round((end - start) * 1000)} ms')
复制代码
逐个记录耗费时间:48 ms
最终记录耗费时间:10 ms

(4)测量同时在两个 GPU 上执行两个矩阵乘法与在一个 GPU 上按顺序执行两个矩阵乘法所需的时间。

相关推荐
张较瘦_2 小时前
[论文阅读] AI+ | 从 “刚性科层” 到 “智能协同”:一文读懂 AI 应对国家安全风险的核心逻辑
论文阅读·人工智能
anscos2 小时前
庭田科技亮相成都复材盛会,以仿真技术赋能产业革新
大数据·人工智能·科技
阿里云大数据AI技术2 小时前
PAI Physical AI Notebook 详解 1:基于 Isaac 仿真的操作动作数据扩增与模仿学习
人工智能
该用户已不存在2 小时前
Vibe Coding 入门指南:从想法到产品的完整路径
前端·人工智能·后端
一只鹿鹿鹿2 小时前
系统安全设计方案书(Word)
开发语言·人工智能·web安全·需求分析·软件系统
Likeadust2 小时前
视频直播点播平台EasyDSS:助力现代农业驶入数字科技“快车道”
人工智能·科技·音视频
南阳木子2 小时前
GEO:AI 时代流量新入口,四川嗨它科技如何树立行业标杆? (2025年10月最新版)
人工智能·科技
oe10192 小时前
好文与笔记分享 A Survey of Context Engineering for Large Language Models(中)
人工智能·笔记·语言模型·agent开发
寒秋丶2 小时前
Milvus:集合(Collections)操作详解(三)
数据库·人工智能·python·ai·ai编程·milvus·向量数据库
寒秋丶2 小时前
Milvus:Schema详解(四)
数据库·人工智能·python·ai·ai编程·milvus·向量数据库