- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Pytorch 高效使用GPU的操作由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
深度学习涉及很多向量或多矩阵运算,如矩阵相乘、矩阵相加、矩阵-向量乘法等。深层模型的算法,如BP,Auto-Encoder,CNN等,都可以写成矩阵运算的形式,无须写成循环运算。然而,在单核CPU上执行时,矩阵运算会被展开成循环的形式,本质上还是串行执行。GPU(Graphic Process Units,图形处理器)的众核体系结构包含几千个流处理器,可将矩阵运算并行化执行,大幅缩短计算时间。随着NVIDIA、AMD等公司不断推进其GPU的大规模并行架构,面向通用计算的GPU已成为加速可并行应用程序的重要手段。得益于GPU众核(many-core)体系结构,程序在GPU系统上的运行速度相较于单核CPU往往提升几十倍乃至上千倍.
目前,GPU已经发展到了较为成熟的阶段。利用GPU来训练深度神经网络,可以充分发挥其数以千计计算核心的能力,在使用海量训练数据的场景下,所耗费的时间大幅缩短,占用的服务器也更少。如果对适当的深度神经网络进行合理优化,一块GPU卡相当于数十甚至上百台CPU服务器的计算能力,因此GPU已经成为业界在深度学习模型训练方面的首选解决方案.
如何使用GPU?现在很多深度学习工具都支持GPU运算,使用时只要简单配置即可。Pytorch支持GPU,可以通过to(device)函数来将数据从内存中转移到GPU显存,如果有多个GPU还可以定位到哪个或哪些GPU。Pytorch一般把GPU作用于张量(Tensor)或模型(包括torch.nn下面的一些网络模型以及自己创建的模型)等数据结构上.
单GPU加速 。
使用GPU之前,需要确保GPU是可以使用,可通过torch.cuda.is_available()的返回值来进行判断。返回True则具有能够使用的GPU.
通过torch.cuda.device_count()可以获得能够使用的GPU数量.
如何查看平台GPU的配置信息?在命令行输入命令nvidia-smi即可 (适合于Linux或Windows环境)。图5-13是GPU配置信息样例,从中可以看出共有2个GPU.
图 GPU配置信息 。
把数据从内存转移到GPU,一般针对张量(我们需要的数据)和模型。 对张量(类型为FloatTensor或者是LongTensor等),一律直接使用方法.to(device)或.cuda()即可.
1
2
3
4
5
6
|
device
=
torch.device(
"cuda:0"
if
torch.cuda.is_available()
else
"cpu"
)
#或device = torch.device("cuda:0")
device1
=
torch.device(
"cuda:1"
)
for
batch_idx, (img, label)
in
enumerate
(train_loader):
img
=
img.to(device)
label
=
label.to(device)
|
对于模型来说,也是同样的方式,使用.to(device)或.cuda来将网络放到GPU显存.
1
2
3
4
|
#实例化网络
model
=
Net()
model.to(device)
#使用序号为0的GPU
#或model.to(device1) #使用序号为1的GPU
|
多GPU加速 。
这里我们介绍单主机多GPUs的情况,单机多GPUs主要采用的DataParallel函数,而不是DistributedParallel,后者一般用于多主机多GPUs,当然也可用于单机多GPU.
使用多卡训练的方式有很多,当然前提是我们的设备中存在两个及以上的GPU.
使用时直接用model传入torch.nn.DataParallel函数即可,如下代码:
#对模型 。
net = torch.nn.DataParallel(model) 。
这时,默认所有存在的显卡都会被使用.
如果你的电脑有很多显卡,但只想利用其中一部分,如只使用编号为0、1、3、4的四个GPU,那么可以采用以下方式:
1
2
3
4
5
6
7
|
#假设有4个GPU,其id设置如下
device_ids
=
[
0
,
1
,
2
,
3
]
#对数据
input_data
=
input_data.to(device
=
device_ids[
0
])
#对于模型
net
=
torch.nn.DataParallel(model)
net.to(device)
|
或者 。
os.environ["CUDA_VISIBLE_DEVICES"] = ','.join(map(str, [0,1,2,3])) 。
net = torch.nn.DataParallel(model) 。
其中CUDA_VISIBLE_DEVICES 表示当前可以被Pytorch程序检测到的GPU.
下面为单机多GPU的实现代码.
背景说明 。
这里使用波士顿房价数据为例,共506个样本,13个特征。数据划分成训练集和测试集,然后用data.DataLoader转换为可批加载的方式。采用nn.DataParallel并发机制,环境有2个GPU。当然,数据量很小,按理不宜用nn.DataParallel,这里只是为了说明使用方法.
加载数据 。
1
2
3
4
5
6
|
boston
=
load_boston()
X,y
=
(boston.data, boston.target)
X_train, X_test, y_train, y_test
=
train_test_split(X, y, test_size
=
0.2
, random_state
=
0
)
#组合训练数据及标签
myset
=
list
(
zip
(X_train,y_train))
|
把数据转换为批处理加载方式批次大小为128,打乱数据 。
1
2
3
4
|
from
torch.utils
import
data
device
=
torch.device(
"cuda:0"
if
torch.cuda.is_available()
else
"cpu"
)
dtype
=
torch.FloatTensor
train_loader
=
data.DataLoader(myset,batch_size
=
128
,shuffle
=
True
)
|
定义网络 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class
Net1(nn.Module):
"""
使用sequential构建网络,Sequential()函数的功能是将网络的层组合到一起
"""
def
__init__(
self
, in_dim, n_hidden_1, n_hidden_2, out_dim):
super
(Net1,
self
).__init__()
self
.layer1
=
torch.nn.Sequential(nn.Linear(in_dim, n_hidden_1))
self
.layer2
=
torch.nn.Sequential(nn.Linear(n_hidden_1, n_hidden_2))
self
.layer3
=
torch.nn.Sequential(nn.Linear(n_hidden_2, out_dim))
def
forward(
self
, x):
x1
=
F.relu(
self
.layer1(x))
x1
=
F.relu(
self
.layer2(x1))
x2
=
self
.layer3(x1)
#显示每个GPU分配的数据大小
print
(
"\tIn Model: input size"
, x.size(),
"output size"
, x2.size())
return
x2
|
把模型转换为多GPU并发处理格式 。
1
2
3
4
5
6
7
8
|
device
=
torch.device(
"cuda:0"
if
torch.cuda.is_available()
else
"cpu"
)
#实例化网络
model
=
Net1(
13
,
16
,
32
,
1
)
if
torch.cuda.device_count() >
1
:
print
(
"Let's use"
, torch.cuda.device_count(),
"GPUs"
)
# dim = 0 [64, xxx] -> [32, ...], [32, ...] on 2GPUs
model
=
nn.DataParallel(model)
model.to(device)
|
运行结果 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Let's use
2
GPUs
DataParallel(
(module): Net1(
(layer1): Sequential(
(
0
): Linear(in_features
=
13
, out_features
=
16
, bias
=
True
)
)
(layer2): Sequential(
(
0
): Linear(in_features
=
16
, out_features
=
32
, bias
=
True
)
)
(layer3): Sequential(
(
0
): Linear(in_features
=
32
, out_features
=
1
, bias
=
True
)
)
)
)
|
选择优化器及损失函数 。
optimizer_orig = torch.optim.Adam(model.parameters(), lr=0.01) 。
loss_func = torch.nn.MSELoss() 。
模型训练,并可视化损失值 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from
torch.utils.tensorboard
import
SummaryWriter
writer
=
SummaryWriter(log_dir
=
'logs'
)
for
epoch
in
range
(
100
):
model.train()
for
data,label
in
train_loader:
input
=
data.
type
(dtype).to(device)
label
=
label.
type
(dtype).to(device)
output
=
model(
input
)
loss
=
loss_func(output, label)
# 反向传播
optimizer_orig.zero_grad()
loss.backward()
optimizer_orig.step()
print
(
"Outside: input size"
,
input
.size() ,
"output_size"
, output.size())
writer.add_scalar(
'train_loss_paral'
,loss, epoch)
|
运行的部分结果 。
1
2
3
4
5
6
|
In Model:
input
size torch.Size([
64
,
13
]) output size torch.Size([
64
,
1
])
In Model:
input
size torch.Size([
64
,
13
]) output size torch.Size([
64
,
1
])
Outside:
input
size torch.Size([
128
,
13
]) output_size torch.Size([
128
,
1
])
In Model:
input
size torch.Size([
64
,
13
]) output size torch.Size([
64
,
1
])
In Model:
input
size torch.Size([
64
,
13
]) output size torch.Size([
64
,
1
])
Outside:
input
size torch.Size([
128
,
13
]) output_size torch.Size([
128
,
1
])
|
从运行结果可以看出,一个批次数据(batch-size=128)拆分成两份,每份大小为64,分别放在不同的GPU上。此时用GPU监控也可发现,两个GPU都同时在使用.
8. 通过web查看损失值的变化情况 。
图 并发运行训练损失值变化情况 。
图形中出现较大振幅,是由于采用批次处理,而且数据没有做任何预处理,对数据进行规范化应该更平滑一些,大家可以尝试一下.
单机多GPU也可使用DistributedParallel,它多用于分布式训练,但也可以用在单机多GPU的训练,配置比使用nn.DataParallel稍微麻烦一点,但是训练速度和效果更好一点。具体配置为:
1
2
3
4
|
#初始化使用nccl后端
torch.distributed.init_process_group(backend
=
"nccl"
)
#模型并行化
model
=
torch.nn.parallel.DistributedDataParallel(model)
|
单机运行时使用下面方法启动 。
python -m torch.distributed.launch main.py 。
使用GPU注意事项 。
使用GPU可以提升我们训练的速度,如果使用不当,可能影响使用效率,具体使用时要注意以下几点:
GPU的数量尽量为偶数,奇数的GPU有可能会出现异常中断的情况; 。
GPU很快,但数据量较小时,效果可能没有单GPU好,甚至还不如CPU; 。
如果内存不够大,使用多GPU训练的时候可通过设置pin_memory为False,当然使用精度稍微低一点的数据类型有时也效果.
以上这篇Pytorch 高效使用GPU的操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我.
原文链接:https://blog.csdn.net/xxboy61/article/details/97973288 。
最后此篇关于Pytorch 高效使用GPU的操作的文章就讲到这里了,如果你想了解更多关于Pytorch 高效使用GPU的操作的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在努力做到这一点 在我的操作中从数据库获取对象列表(确定) 在 JSP 上打印(确定) 此列表作为 JSP 中的可编辑表出现。我想修改然后将其提交回同一操作以将其保存在我的数据库中(失败。当我使用
我有以下形式的 Linq to Entities 查询: var x = from a in SomeData where ... some conditions ... select
我有以下查询。 var query = Repository.Query() .Where(p => !p.IsDeleted && p.Article.ArticleSections.Cou
我正在编写一个应用程序包,其中包含一个主类,其中主方法与GUI类分开,GUI类包含一个带有jtabbedpane的jframe,它有两个选项卡,第一个选项卡包含一个jtable,称为jtable1,第
以下代码产生错误 The nested query is not supported. Operation1='Case' Operation2='Collect' 问题是我做错了什么?我该如何解决?
我已经为 HA redis 集群(2 个副本、1 个主节点、3 个哨兵)设置了本地 docker 环境。只有哨兵暴露端口(10021、10022、10023)。 我使用的是 stackexchange
我正在 Desk.com 中构建一个“集成 URL”,它使用 Shopify Liquid 模板过滤器语法。对于开始日期为 7 天前而结束日期为现在的查询,此 URL 需要包含“开始日期”和“结束日期
你一定想过。然而情况却不理想,python中只能使用类似于 i++/i--等操作。 python中的自增操作 下面代码几乎是所有程序员在python中进行自增(减)操作的常用
我需要在每个使用 github 操作的手动构建中显示分支。例如:https://gyazo.com/2131bf83b0df1e2157480e5be842d4fb 我应该显示分支而不是一个。 最佳答
我有一个关于 Perl qr 运算符的问题: #!/usr/bin/perl -w &mysplit("a:b:c", /:/); sub mysplit { my($str, $patt
我已经使用 ArgoUML 创建了一个 ERD(实体关系图),我希望在一个类中创建两个操作,它们都具有 void 返回类型。但是,我只能创建一个返回 void 类型的操作。 例如: 我能够将 book
Github 操作仍处于测试阶段并且很新,但我希望有人可以提供帮助。我认为可以在主分支和拉取请求上运行 github 操作,如下所示: on: pull_request push: b
我正在尝试创建一个 Twilio 工作流来调用电话并记录用户所说的内容。为此,我正在使用 Record,但我不确定要在 action 参数中放置什么。 尽管我知道 Twilio 会发送有关调用该 UR
我不确定这是否可行,但值得一试。我正在使用模板缓冲区来减少使用此算法的延迟渲染器中光体积的过度绘制(当相机位于体积之外时): 使用廉价的着色器,将深度测试设置为 LEQUAL 绘制背面,将它们标记在模
有没有聪明的方法来复制 和 重命名 文件通过 GitHub 操作? 我想将一些自述文件复制到 /docs文件夹(:= 同一个 repo,不是远程的!),它们将根据它们的 frontmatter 重命名
我有一个 .csv 文件,其中第一列包含用户名。它们采用 FirstName LastName 的形式。我想获取 FirstName 并将 LastName 的第一个字符添加到它上面,然后删除空格。然
Sitecore 根据 Sitecore 树中定义的项目名称生成 URL, http://samplewebsite/Pages/Sample Page 但我们的客户有兴趣降低所有 URL(页面/示例
我正在尝试进行一些计算,但是一旦我输入金额,它就会完成。我只是希望通过单击按钮而不是自动发生这种情况。 到目前为止我做了什么: Angular JS - programming-fr
我的公司创建了一种在环境之间移动文件的复杂方法,现在我们希望将某些构建的 JS 文件(已转换和缩小)从一个 github 存储库移动到另一个。使用 github 操作可以实现这一点吗? 最佳答案 最简
在我的代码中,我创建了一个 JSONArray 对象。并向 JSONArray 对象添加了两个 JSONObject。我使用的是 json-simple-1.1.jar。我的代码是 package j
我是一名优秀的程序员,十分优秀!