GPU的使用
1. 数据迁移至GPU
to函数:转换数据类型/设备
区别:张量不执行inplace,模型执行inplace
1 | x = torch.ones((3, 3)) |
实验:
-
tensor to cuda
1
2
3
4
5
6
7
8import torch
import torch.nn as nn
x_cpu = torch.ones((3, 3))
print("x_cpu:\ndevice: {} is_cuda: {} id: {}".format(x_cpu.device, x_cpu.is_cuda, id(x_cpu)))
x_gpu = x_cpu.to('cuda')
print("x_gpu:\ndevice: {} is_cuda: {} id: {}".format(x_gpu.device, x_gpu.is_cuda, id(x_gpu)))输出
1
2
3
4x_cpu:
device: cpu is_cuda: False id: 2141032222976
x_gpu:
device: cuda:0 is_cuda: True id: 2138929688384转换前后id不同,说明不是inplace操作,划分了新的内存地址
-
module to cuda
1
2
3
4
5
6
7
8
9import torch
import torch.nn as nn
net = nn.Sequential(nn.Linear(3, 3))
print("\nid:{} is_cuda: {}".format(id(net), next(net.parameters()).is_cuda))
net.to('cuda')
print("\nid:{} is_cuda: {}".format(id(net), next(net.parameters()).is_cuda))输出
1
2
3id:2455688847568 is_cuda: False
id:2455688847568 is_cuda: True模型转换是inplace操作
-
forward in cuda
1
2
3
4
5
6
7
8
9import torch
import torch.nn as nn
x_cpu = torch.ones((3, 3))
x_gpu = x_cpu.to('cuda')
net = nn.Sequential(nn.Linear(3, 3))
output = net(x_gpu)
print("output is_cuda: {}".format(output.is_cuda))输出
1
output is_cuda: True
2. torch.cuda常用方法
-
torch.cuda.device_count():计算当前可见可用gpu数
-
torch.cuda.get_device_name():获取gpu名称
-
torch.cuda.is_available():返回True则说明cuda可用(安装的是cuda版的pytorch)
-
torch.cuda.manual_seed():为当前gpu设置随机种子
-
torch.cuda.manual_seed_all():为所有可见可用gpu设置随机种子
-
torch.cuda.set_device():设置主gpu为哪一个物理gpu(不推荐)
推荐: os.environ.setdefault(“CUDA_VISIBLE_DEVICES”, “2, 3”)
通过设置环境将逻辑gpu映射为物理gpu;os.environ.setdefault(“CUDA_VISIBLE_DEVICES”, “2, 3”)这句话的意思就是设置逻辑gpu0、逻辑gpu1为物理gpu2,物理gpu3。
3. 多GPU并行运算
1 | torch.nn.DataParallel(module, |
功能:包装模型,实现分发并行机制
主要参数:
- module: 需要包装分发的模型
- device_ids: 可分发的gpu,默认分发到所有可见可用gpu
- output_device: 结果输出设备
实验:
1 | import os |
输出:
1 | batch size in forward: 16 |
我的电脑只有一个GPU,因此batch size in forward = 16
如果我们在选择GPU时设置为gpu_list = [1]
,将逻辑GPU0映射为物理GPU1,那么运行代码后的结果如下所示:
1 | batch size in forward: 16 |
显然我们是没有物理GPU1的,因此device_count=0
下面是一台有四个GPU(选择了2、3号GPU)的电脑运行上面程序的结果:
1 | batch size in forward: 8 |
4. GPU加载常见报错
报错1:
RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU -only machine, please use torch.load with map_location=torch.device(‘cpu’) to map your storages to the CPU.
这个错误是因为保存模型是保存在了cuda上,而加载的电脑并不能使用cuda时,就会有这个错误。
解决:
1 | torch.load(path_state_dict, map_location="cpu") |
报错2:
RuntimeError: Error(s) in loading state_dict for FooNet:Missing key(s) in state_dict: “linears.0.weight”, “linears.1.weight”, “linears.2.weight”. Unexpected key(s) in state_dict: “module.linears.0.weight”, “module.linears.1.weight”, “module.linears.2.weight”.
这个错误是因为当使用了torch.nn.DataParallel
进行多GPU运算时,这个函数会把state_dict的键的名称前面加上一个module.的前缀(共7个字符)
解决:
1 | from collections import OrderedDict |