将Pytorch模型从CPU转换成GPU的实现方法

最近将Pytorch程序迁移到GPU上去的一些工作和思考

环境:Ubuntu 16.04.3

Python版本:3.5.2

Pytorch版本:0.4.0

0. 序言

大家知道,在深度学习中使用GPU来对模型进行训练是可以通过并行化其计算来提高运行效率,这里就不多谈了。

最近申请到了实验室的服务器来跑程序,成功将我简陋的程序改成了“高大上”GPU版本。

看到网上总体来说少了很多介绍,这里决定将我的一些思考和工作记录下来。

1. 如何进行迁移

由于我使用的是Pytorch写的模型,网上给出了一个非常简单的转换方式: 对模型和相应的数据进行.cuda()处理。通过这种方式,我们就可以将内存中的数据复制到GPU的显存中去。从而可以通过GPU来进行运算了。

网上说的非常简单,但是实际使用过程中还是遇到了一些疑惑。下面分数据和模型两方面的迁移来进行说明介绍。

1.1 判定使用GPU

下载了对应的GPU版本的Pytorch之后,要确保GPU是可以进行使用的,通过torch.cuda.is_available()的返回值来进行判断。返回True则具有能够使用的GPU。

通过torch.cuda.device_count()可以获得能够使用的GPU数量。其他就不多赘述了。

常常通过如下判定来写可以跑在GPU和CPU上的通用模型:

if torch.cuda.is_available():
  ten1 = ten1.cuda()
  MyModel = MyModel.cuda() 

2. 对应数据的迁移

数据方面常用的主要是两种 —— Tensor和Variable。实际上这两种类型是同一个东西,因为Variable实际上只是一个容器,这里先视其不同。

2.1 将Tensor迁移到显存中去

不论是什么类型的Tensor(FloatTensor或者是LongTensor等等),一律直接使用方法.cuda()即可。

例如:

ten1 = torch.FloatTensor(2)
>>>> 6.1101e+24
   4.5659e-41
   [torch.FloatTensor of size 2]

ten1_cuda = ten1.cuda()
>>>>  6.1101e+24
    4.5659e-41
    [torch.cuda.FloatTensor of size 2 (GPU 0)]

其数据类型会由torch.FloatTensor变为torch.cuda.FloatTensor (GPU 0)这样代表这个数据现在存储在

GPU 0的显存中了。

如果要将显存中的数据复制到内存中,则对cuda数据类型使用.cpu()方法即可。

2.2 将Variable迁移到显存中去

在模型中,我们最常使用的是Variable这个容器来装载使用数据。主要是由于Variable可以进行反向传播来进行自动求导。

同样地,要将Variable迁移到显存中,同样只需要使用.cuda()即可实现。

这里有一个小疑问,对Variable直接使用.cuda和对Tensor进行.cuda然后再放置到Variable中结果是否一致呢。答案是肯定的。

ten1 = torch.FloatTensor(2)
>>> 6.1101e+24
   4.5659e-41
  [torch.FloatTensor of size 2]

ten1_cuda = ten1.cuda()
>>>> 6.1101e+24
   4.5659e-41
  [torch.cuda.FloatTensor of size 2 (GPU 0)]

V1_cpu = autograd.Variable(ten1)
>>>> Variable containing:
   6.1101e+24
   4.5659e-41
  [torch.FloatTensor of size 2]

V2 = autograd.Variable(ten1_cuda)
>>>> Variable containing:
   6.1101e+24
   4.5659e-41
  [torch.cuda.FloatTensor of size 2 (GPU 0)]

V1 = V1_cpu.cuda()
>>>> Variable containing:
   6.1101e+24
   4.5659e-41
  [torch.cuda.FloatTensor of size 2 (GPU 0)]

最终我们能发现他们都能够达到相同的目的,但是他们完全一样了吗?我们使用V1 is V2发现,结果是否定的。

对于V1,我们是直接对Variable进行操作的,这样子V1的.grad_fn中会记录下创建的方式。因此这二者并不是完全相同的。

2.3 数据迁移小结

.cuda()操作默认使用GPU 0也就是第一张显卡来进行操作。当我们想要存储在其他显卡中时可以使用.cuda(<显卡号数>)来将数据存储在指定的显卡中。还有很多种方式,具体参考官方文档。

对于不同存储位置的变量,我们是不可以对他们直接进行计算的。存储在不同位置中的数据是不可以直接进行交互计算的。

换句话说也就是上面例子中的torch.FloatTensor是不可以直接与torch.cuda.FloatTensor进行基本运算的。位于不同GPU显存上的数据也是不能直接进行计算的。

对于Variable,其实就仅仅是一种能够记录操作信息并且能够自动求导的容器,实际上的关键信息并不在Variable本身,而更应该侧重于Variable中存储的data。

3. 模型迁移

模型的迁移这里指的是torch.nn下面的一些网络模型以及自己创建的模型迁移到GPU上去。

上面讲了使用.cuda()即可将数据从内存中移植到显存中去。

对于模型来说,也是同样的方式,我们使用.cuda来将网络放到显存上去。

3.1 torch.nn下的基本模型迁移

这里使用基本的单层感知机来进行举例(线性模型)。

data1 = torch.FloatTensor(2)
data2 = data1.cuda

# 创建一个输入维度为2,输出维度为2的单层神经网络
linear = torch.nn.Linear(2, 2)
>>>> Linear(in_features=2, out_features=2)

linear_cuda = linear.cuda()
>>>> Linear(in_features=2, out_features=2)

我们很惊奇地发现对于模型来说,不像数据那样使用了.cuda()之后会改变其的数据类型。模型看起来没有任何的变化。

但是他真的没有改变吗。

我们将data1投入linear_cuda中去可以发现,系统会报错,而将.cuda之后的data2投入linear_cuda才能正常工作。并且输出的也是具有cuda的数据类型。

那是怎么一回事呢?

这是因为这些所谓的模型,其实也就是对输入参数做了一些基本的矩阵运算。所以我们对模型.cuda()实际上也相当于将模型使用到的参数存储到了显存上去。

对于上面的例子,我们可以通过观察参数来发现区别所在。

linear.weight
>>>> Parameter containing:
  -0.6847 0.2149
  -0.5473 0.6863
  [torch.FloatTensor of size 2x2]

linear_cuda.weight
>>>> Parameter containing:
  -0.6847 0.2149
  -0.5473 0.6863
  [torch.cuda.FloatTensor of size 2x2 (GPU 0)]

3.2 自己模型的迁移

对于自己创建的模型类,由于继承了torch.nn.Module,则可同样使用.cuda()来将模型中用到的所有参数都存储到显存中去。

这里笔者曾经有一个疑问:当我们对模型存储到显存中去之后,那么这个模型中的方法后面所创建出来的Tensor是不是都会默认变成cuda的数据类型。答案是否定的。具体操作留给读者自己去实现。

3.3 模型小结

对于模型而言,我们可以将其看做是一种类似于Variable的容器。我们对它进行.cuda()处理,是将其中的参数放到显存上去(因为实际使用的时候也是通过这些参数做运算)。

4. 总结

Pytorch使用起来直接简单,GPU的使用也是简单明了。然而对于多GPU和CPU的协同使用则还是有待提高。

以上这篇将Pytorch模型从CPU转换成GPU的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • pytorch 使用单个GPU与多个GPU进行训练与测试的方法

    如下所示: device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")#第一行代码 model.to(device)#第二行代码 首先是上面两行代码放在读取数据之前. mytensor = my_tensor.to(device)#第三行代码 然后是第三行代码.这句代码的意思是将所有最开始读取数据时的tersor变量copy一份到device所指定的GPU上去,之后的运算都在GPU上

  • 在pytorch中为Module和Tensor指定GPU的例子

    pytorch指定GPU 在用pytorch写CNN的时候,发现一运行程序就卡住,然后cpu占用率100%,nvidia-smi 查看显卡发现并没有使用GPU.所以考虑将模型和输入数据及标签指定到gpu上. pytorch中的Tensor和Module可以指定gpu运行,并且可以指定在哪一块gpu上运行,方法非常简单,就是直接调用Tensor类和Module类中的 .cuda() 方法. import torch from PIL import Image import torch.nn as

  • pytorch使用指定GPU训练的实例

    本文适合多GPU的机器,并且每个用户需要单独使用GPU训练. 虽然pytorch提供了指定gpu的几种方式,但是使用不当的话会遇到out of memory的问题,主要是因为pytorch会在第0块gpu上初始化,并且会占用一定空间的显存.这种情况下,经常会出现指定的gpu明明是空闲的,但是因为第0块gpu被占满而无法运行,一直报out of memory错误. 解决方案如下: 指定环境变量,屏蔽第0块gpu CUDA_VISIBLE_DEVICES = 1 main.py 这句话表示只有第1块

  • 关于pytorch多GPU训练实例与性能对比分析

    以下实验是我在百度公司实习的时候做的,记录下来留个小经验. 多GPU训练 cifar10_97.23 使用 run.sh 文件开始训练 cifar10_97.50 使用 run.4GPU.sh 开始训练 在集群中改变GPU调用个数修改 run.sh 文件 nohup srun --job-name=cf23 $pt --gres=gpu:2 -n1 bash cluster_run.sh $cmd 2>&1 1>>log.cf50_2GPU & 修改 –gres=gpu:

  • 将Pytorch模型从CPU转换成GPU的实现方法

    最近将Pytorch程序迁移到GPU上去的一些工作和思考 环境:Ubuntu 16.04.3 Python版本:3.5.2 Pytorch版本:0.4.0 0. 序言 大家知道,在深度学习中使用GPU来对模型进行训练是可以通过并行化其计算来提高运行效率,这里就不多谈了. 最近申请到了实验室的服务器来跑程序,成功将我简陋的程序改成了"高大上"GPU版本. 看到网上总体来说少了很多介绍,这里决定将我的一些思考和工作记录下来. 1. 如何进行迁移 由于我使用的是Pytorch写的模型,网上给

  • pytorch 把MNIST数据集转换成图片和txt的方法

    本文介绍了pytorch 把MNIST数据集转换成图片和txt的方法,分享给大家,具体如下: 1.下载Mnist 数据集 import os # third-party library import torch import torch.nn as nn from torch.autograd import Variable import torch.utils.data as Data import torchvision import matplotlib.pyplot as plt # t

  • php实现图片转换成ASCII码的方法

    本文实例讲述了php实现图片转换成ASCII码的方法.分享给大家供大家参考.具体如下: php图片转换成ASCII码,转换后可以直接通过字符串显示图片 <html> <head> <title>Ascii</title> <style> body{ line-height:0; font-size:1px; } </style> </head> <body> <?php $image = 'image.j

  • php将图片文件转换成二进制输出的方法

    本文实例讲述了php将图片文件转换成二进制输出的方法.分享给大家供大家参考.具体实现方法如下: header( "Content-type: image/jpeg"); $PSize = filesize('1.jpg'); $picturedata = fread(fopen('1.jpg', "r"), $PSize); echo $picturedata; 就这么简单4行代码,就将图片以二进制流的形式输出到客户端了,和打开一张图片没有任何区别. 这里需要注意的

  • python实现将html表格转换成CSV文件的方法

    本文实例讲述了python实现将html表格转换成CSV文件的方法.分享给大家供大家参考.具体如下: 使用方法:python html2csv.py *.html 这段代码使用了 HTMLParser 模块 #!/usr/bin/python # -*- coding: iso-8859-1 -*- # Hello, this program is written in Python - http://python.org programname = 'html2csv - version 20

  • JavaScript将数字转换成大写中文的方法

    本文实例讲述了JavaScript将数字转换成大写中文的方法.分享给大家供大家参考.具体实现方法如下: function intToChinese ( str ) { str = str+''; var len = str.length-1; var idxs = ['','十','百','千','万','十','百','千','亿','十','百','千','万','十','百','千','亿']; var num = ['零','壹','贰','叁','肆','伍','陆','柒','捌',

  • 将JSON字符串转换成Map对象的方法

    页面向后台action传递一个json字符串,需要将json字符串转换成Map对象 public Map<String, String> toMap(Object object) { Map<String, String> data = new HashMap<String, String>(); // 将json字符串转换成jsonObject JSONObject jsonObject = JSONObject.fromObject(object); Iterato

  • python将文本转换成图片输出的方法

    本文实例讲述了python将文本转换成图片输出的方法.分享给大家供大家参考.具体实现方法如下: #-*- coding:utf-8 -*- from PIL import Image,ImageFont,ImageDraw text = u'欢迎访问我们,http://www.jb51.net' font = ImageFont.truetype("msyh.ttf",18) lines = [] line ='' for word in text.split(): print wor

  • python将图片文件转换成base64编码的方法

    本文实例讲述了python将图片文件转换成base64编码的方法.分享给大家供大家参考.具体实现方法如下: import base64 f=open(r'c:\jb51.gif','rb') #二进制方式打开图文件 ls_f=base64.b64encode(f.read()) #读取文件内容,转换为base64编码 f.close() 调用方法如下: 复制代码 代码如下: <img src="R0lGODlh1wBOAPcAAAAAAP///7a4u+jq7bG1ucrN0N7g4tLU

  • python通过pil模块将raw图片转换成png图片的方法

    本文实例讲述了python通过pil模块将raw图片转换成png图片的方法.分享给大家供大家参考.具体分析如下: python通过pil模块将raw图片转换成png图片,pil中包含了fromstring函数可以按照指定模式读取图片信息然后进行保存. rawData = open("foo.raw" 'rb').read() imgSize = (x,y) # Use the PIL raw decoder to read the data. # the 'F;16' informs

随机推荐