PyTorch中的CUDA的操作方法

目录
  • 前言
  • 一.常见CPU和GPU操作命令
  • 二.CPU和GPU设备上的Tensor
    • 1.Tensor从CPU拷贝到GPU上
    • 2.直接在GPU上创建Tensor
    • 3.CUDA Streams
  • 三.固定缓冲区
  • 四.自动设备感知
    • 1.适配CPU和GPU设备
    • 2.模型迁移到GPU设备

前言

CUDA(Compute Unified Device Architecture)是NVIDIA推出的异构计算平台,PyTorch中有专门的模块torch.cuda来设置和运行CUDA相关操作。本地安装环境为Windows10,Python3.7.8和CUDA 11.6,安装PyTorch最新稳定版本1.12.1如下:

pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu116

一.常见CPU和GPU操作命令

1.查看PyTorch版本

print(torch.__version__)
1.12.1+cu116

2.查看GPU设备是否可用

print(torch.cuda.is_available())
True

3.PyTorch默认使用设备是CPU

print("default device: {}".format(torch.Tensor([4,5,6]).device))
default device: cpu

4.查看所有可用的cpu设备的数量

print("available cpu devices: {}".format(torch.cuda.os.cpu_count()))
available cpu devices: 20

这里CPU设备数量指的是逻辑处理器的数量。

5.查看所有可用的gpu设备的数量

print("available gpu devices: {}".format(torch.cuda.device_count()))
available gpu devices: 1

6.获取gpu设备的名称

print("gpu device name: {}".format(torch.cuda.get_device_name(torch.device("cuda:0"))))
gpu device name: NVIDIA GeForce GTX 1080 Ti

7.通过device="cpu:0"指定cpu:0设备

device = torch.Tensor([1,2,3], device="cpu:0").device
print("device type: {}".format(device))
device type: cpu

8.通过torch.device指定cpu:0设备

cpu1 = torch.device("cpu:0")
print("cpu device: {}:{}".format(cpu1.type, cpu1.index))
cpu device: cpu:0

9.使用索引的方式,默认使用CUDA设备

gpu = torch.device(0)
print("gpu device: {}:{}".format(gpu.type, gpu.index))
gpu device: cuda:0

10.通过torch.device("cuda:0)指定cuda:0设备

gpu = torch.device("cuda:0")
print("gpu device: {}:{}".format(gpu.type, gpu.index))
gpu device: cuda:0

二.CPU和GPU设备上的Tensor

默认情况下创建Tensor是在CPU设备上的,但是可以通过copy_、to、cuda等方法将CPU设备中的Tensor转移到GPU设备上。当然也是可以直接在GPU设备上创建Tensor的。torch.tensor和torch.Tensor的区别是,torch.tensor可以通过device指定gpu设备,而torch.Tensor只能在cpu上创建,否则报错。

1.Tensor从CPU拷贝到GPU上

# 默认创建的tensor是在cpu上创建的
cpu_tensor = torch.Tensor([[1,4,7],[3,6,9],[2,5,8]])
print(cpu_tensor.device)

# 通过to方法将cpu_tensor拷贝到gpu上
gpu_tensor1 = cpu_tensor.to(torch.device("cuda:0"))
print(gpu_tensor1.device)

# 通过cuda方法将cpu_tensor拷贝到gpu上
gpu_tensor2 = cpu_tensor.cuda(torch.device("cuda:0"))
print(gpu_tensor2.device)

# 将gpu_tensor2拷贝到cpu上
gpu_tensor3 = cpu_tensor.copy_(gpu_tensor2)
print(gpu_tensor3.device)
print(gpu_tensor3)

输出结果如下:

cpu
cuda:0
cuda:0
cpu
tensor([[1., 4., 7.],
        [3., 6., 9.],
        [2., 5., 8.]])

主要说明下这个copy_()方法,实现如下:

def copy_(self, src, non_blocking=False):
    ......
    return _te.Tensor(*(), **{})

就是从src中拷贝元素到self的tensor中,然后返回self。以gpu_tensor3 = cpu_tensor.copy_(gpu_tensor2)为例,就是把gpu中的gpu_tensor2拷贝到cpu中的cpu_tensor中。

2.直接在GPU上创建Tensor

gpu_tensor1 = torch.tensor([[2,5,8],[1,4,7],[3,6,9]], device=torch.device("cuda:0"))
print(gpu_tensor1.device)

# 在gpu设备上创建随机数tensor
print(torch.rand((3,4), device=torch.device("cuda:0")))

# 在gpu设备上创建0值tensor
print(torch.zeros((2,5), device=torch.device("cuda:0")))

输出结果,如下:

cuda:0
tensor([[0.7061, 0.2161, 0.8219, 0.3354],
        [0.1697, 0.1730, 0.1400, 0.2825],
        [0.1771, 0.0473, 0.8411, 0.2318]], device='cuda:0')
tensor([[0., 0., 0., 0., 0.],
        [0., 0., 0., 0., 0.]], device='cuda:0')

3.CUDA Streams

Steam是CUDA命令线性执行的抽象形式,分配给设备的CUDA命令按照入队序列的顺序执行。每个设备都有一个默认的Steam,也可以通过torch.cuda.Stream()创建新的Stream。如果不同Stream中的命令交互执行,那么就不能保证命令绝对按顺序执行。下面的这个例子不同的Stream就可能会产生错误。

cuda = torch.device("cuda")
# 创建默认的stream,A就是使用的默认stream
s = torch.cuda.Stream()
A = torch.randn((1,10), device=cuda)
for i in range(100):
    # 在新的stream上对默认的stream上创建的tensor进行求和
    with torch.cuda.stream(s):
        # 存在的问题是:torch.sum()可能会在torch.randn()之前执行
        B = torch.sum(A)
        print(B)

这个例子存在的问题是torch.sum()可能会在torch.randn()之前就执行。为了保证Stream中的命令绝对按顺序执行,接下来使用Synchronize同步方法解决上面例子的问题:

cuda = torch.device("cuda")
s = torch.cuda.Stream()
A = torch.randn((1,10), device=cuda)
default_stream = torch.cuda.current_stream()
print("Default Stream: {}".format(default_stream))
# 等待创建A的stream执行完毕
torch.cuda.Stream.synchronize(default_stream)
for i in range(100):
    # 在新的stream上对默认的stream上创建的tensor进行求和
    with torch.cuda.stream(s):
        print("current stream: {}".format(torch.cuda.current_stream()))
        B = torch.sum(A)
        print(B)

解决问题的思路就是通过torch.cuda.Stream.synchronize(default_stream)等待创建A的stream执行完毕,然后再执行新的Stream中的指令。
除此之外,使用memory_cached方法获取缓存内存的大小,使用max_memory_cached方法获取最大缓存内存的大小,使用max_memory_allocated方法获取最大分配内存的大小。可以使用empty_cache方法释放无用的缓存内存。

三.固定缓冲区

缓存就是当计算机内存不足的时候,就会把内存中的数据存储到硬盘上。固定缓冲区就是说常驻内存,不能把这部分数据缓存到硬盘上。可以直接使用pin_memory方法或在Tensor上直接调用pin_memory方法将Tensor复制到固定缓冲区。为什么要做固定缓冲区呢?目的只有一个,就是把CPU上的固定缓冲区拷贝到GPU上时速度快。Tensor上的is_pinned方法可以查看该Tensor是否加载到固定缓冲区中。

from torch.utils.data._utils.pin_memory import pin_memory
x = torch.Tensor([[1,2,4], [5, 7, 9], [3, 7, 10]])
# 通过pin_memory()方法将x复制到固定缓冲区
y = pin_memory(x)
# 在tensor上直接调用pin_memory()方法将tensor复制到固定缓冲区
z = x.pin_memory()
# id()方法返回tensor的内存地址,pin_memory()返回tensor对象的拷贝,因此内存地址是不同的
print("id: {}".format(id(x)))
print("id: {}".format(id(y)))
print("id: {}".format(id(z)))
# 当tensor放入固定缓冲区后,就可以异步将数据复制到gpu设备上了
a = z.cuda(non_blocking=True)
print(a)
print("is_pinned: {}/{}".format(x.is_pinned(), z.is_pinned()))

输出结果如下所示:

id: 1605289350472
id: 1605969660408
id: 1605969660248
tensor([[ 1.,  2.,  4.],
        [ 5.,  7.,  9.],
        [ 3.,  7., 10.]], device='cuda:0')
is_pinned: False/True

说明:通过id()查看对象的内存地址。

四.自动设备感知

1.适配CPU和GPU设备

自动设备感知本质上就是有GPU时就使用GPU,没有GPU时就使用CPU,即一套代码适配CPU和GPU设备。GPU是否存在是通过torch.cuda.is_available()判断的。

常见的写法如下:

device = torch.device("cpu")
if torch.cuda.is_available():
    device = torch.device("cuda")
a = torch.tensor([1,2,3], device=device)
print(a)

输出结果如下所示

tensor([1, 2, 3], device='cuda:0')

2.模型迁移到GPU设备

在Module对象上调用to()方法可以把模型也迁移到GPU设备上,如下所示:

class LinearRegression(torch.nn.Module):
    def __init__(self):
        super(LinearRegression, self).__init__()
        self.linear = torch.nn.Linear(1, 1)
    def forward(self, x):
        return self.linear(x)
regression = LinearRegression().to(device=device)
for param in regression.parameters():
    print(param)

从上述输出参数中可以看到param都是device='cuda:0’上的tensor,所以可以说模型通过to()迁移到GPU设备上了。

到此这篇关于PyTorch中的CUDA的操作方法的文章就介绍到这了,更多相关PyTorch CUDA操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PyTorch CUDA环境配置及安装的步骤(图文教程)

    Pytorch版本介绍 torch:1.6 CUDA:10.2 cuDNN:8.1.0 ✨安装 NVIDIA 显卡驱动程序 一般 电脑出厂/装完系统 会自动安装显卡驱动 如果有 可直接进行下一步 下载链接 http://www.nvidia.cn/Download/index.aspx?lang=cn 选择和自己显卡相匹配的显卡驱动 下载安装 ✨确认项目所需torch版本 # pip install -r requirements.txt # base ---------------------

  • 安装pytorch报错torch.cuda.is_available()=false问题的解决过程

    问题介绍 在安装torch之后,命令行(Anaconda Powershell Prompt)运行这三行代码: python # python import torch torch.cuda.is_available() 返回结果始终为False. 出错原因 原因有多个,可以参考文章最后的链接[1] 他的很清晰,如果按我的没有解决可以看一下. 主要就是以下两个: CUDA.cudnn.torch版本不对应.(解决方法参考链接[1]) 一个坑:是通过清华源下载的!检查是不是清华源下载导致的问题:

  • pytorch中.to(device) 和.cuda()的区别说明

    原理 .to(device) 可以指定CPU 或者GPU device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 单GPU或者CPU model.to(device) #如果是多GPU if torch.cuda.device_count() > 1: model = nn.DataParallel(model,device_ids=[0,1,2]) model.to(

  • 将pytorch的网络等转移到cuda

    神经网络一般用GPU来跑,我们的神经网络框架一般也都安装的GPU版本,本文就简单记录一下GPU使用的编写. GPU的设置不在model,而是在Train的初始化上. 第一步是查看是否可以使用GPU self.GPU_IN_USE = torch.cuda.is_available() 就是返回这个可不可以用GPU的函数,当你的pytorch是cpu版本的时候,他就会返回False. 然后是: self.device = torch.device('cuda' if self.GPU_IN_USE

  • pytorch cuda上tensor的定义 以及减少cpu的操作详解

    cuda上tensor的定义 a = torch.ones(1000,1000,3).cuda() 某一gpu上定义 cuda1 = torch.device('cuda:1') b = torch.randn((1000,1000,1000),device=cuda1) 删除某一变量 del a 在cpu定义tensor然后转到gpu torch.zeros().cuda() 直接在gpu上定义,这样就减少了cpu的损耗 torch.cuda.FloatTensor(batch_size, s

  • pytorch 如何用cuda处理数据

    1 设置GPU的一些操作 设置在os端哪些GPU可见,如果不可见,那肯定是不能够调用的~ import os GPU = '0,1,2' os.environ['CUDA_VISIBLE_DEVICES'] =GPU torch.cuda.is_available()查看cuda是否可用. if torch.cuda.is_available(): torch.backends.cudnn.benchmark = True ''' 如果网络的输入数据维度或类型上变化不大,设置 torch.bac

  • PyTorch device与cuda.device用法

    1 查看当前的device 输入情况: import torch print("Default Device : {}".format(torch.Tensor([4, 5, 6]).device)) 输出情况: Default Device : cpu 2 cpu设备可以使用“cpu:0”来指定 输入情况 device = torch.Tensor([1, 2, 3], device="cpu:0").device print("Device Type:

  • pytorch model.cuda()花费时间很长的解决

    解决方法之一: 如果pytorch在进行model.cuda()操作需要花费的时间很长,长到你怀疑GPU的速度了,那就是不正常的. 如果你用的pytorch版本是0.3.0,升级到0.3.1就好了! .cuda()加载时间很长的其他解决方法 方法一: pip install --upgrade --force-reinstall http://download.pytorch.org/whl/cu80/torch-0.2.0.post3-cp27-cp27mu-manylinux1_x86_64

  • PyTorch中的CUDA的操作方法

    目录 前言 一.常见CPU和GPU操作命令 二.CPU和GPU设备上的Tensor 1.Tensor从CPU拷贝到GPU上 2.直接在GPU上创建Tensor 3.CUDA Streams 三.固定缓冲区 四.自动设备感知 1.适配CPU和GPU设备 2.模型迁移到GPU设备 前言 CUDA(Compute Unified Device Architecture)是NVIDIA推出的异构计算平台,PyTorch中有专门的模块torch.cuda来设置和运行CUDA相关操作.本地安装环境为Wind

  • pytorch中使用cuda扩展的实现示例

    以下面这个例子作为教程,实现功能是element-wise add: (pytorch中想调用cuda模块,还是用另外使用C编写接口脚本) 第一步:cuda编程的源文件和头文件 // mathutil_cuda_kernel.cu // 头文件,最后一个是cuda特有的 #include <curand.h> #include <stdio.h> #include <math.h> #include <float.h> #include "math

  • 如何在conda虚拟环境中配置cuda+cudnn+pytorch深度学习环境

    首先,我们要明确,我们是要在虚拟环境中安装cuda和cuDNN!!!只需要在虚拟环境中安装就可以了. 下面的操作默认你安装好了python 一.conda创建并激活虚拟环境 前提:确定你安装好了anaconda并配置好了环境变量,如果没有,网上有很多详细的配置教程,请自行学习 在cmd命令提示符中输入conda命令查看anaconda 如果显示和上图相同,那么可以继续向下看 1.进入anaconda的base环境 方法1 在cmd命令提示符中输入如下命令 activate 方法2 直接在搜索栏里

  • 在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中网络loss传播和参数更新的理解

    相比于2018年,在ICLR2019提交论文中,提及不同框架的论文数量发生了极大变化,网友发现,提及tensorflow的论文数量从2018年的228篇略微提升到了266篇,keras从42提升到56,但是pytorch的数量从87篇提升到了252篇. TensorFlow: 228--->266 Keras: 42--->56 Pytorch: 87--->252 在使用pytorch中,自己有一些思考,如下: 1. loss计算和反向传播 import torch.nn as nn

  • 对pytorch中的梯度更新方法详解

    背景 使用pytorch时,有一个yolov3的bug,我认为涉及到学习率的调整.收集到tencent yolov3和mxnet开源的yolov3,两个优化器中的学习率设置不一样,而且使用GPU数目和batch的更新也不太一样.据此,我简单的了解了下pytorch的权重梯度的更新策略,看看能否一窥究竟. 对代码说明 共三个实验,分布写在代码中的(一)(二)(三)三个地方.运行实验时注释掉其他两个 实验及其结果 实验(三): 不使用zero_grad()时,grad累加在一起,官网是使用accum

  • Pytorch 中retain_graph的用法详解

    用法分析 在查看SRGAN源码时有如下损失函数,其中设置了retain_graph=True,其作用是什么? ############################ # (1) Update D network: maximize D(x)-1-D(G(z)) ########################### real_img = Variable(target) if torch.cuda.is_available(): real_img = real_img.cuda() z = V

  • Pytorch中.new()的作用详解

    一.作用 创建一个新的Tensor,该Tensor的type和device都和原有Tensor一致,且无内容. 二.使用方法 如果随机定义一个大小的Tensor,则新的Tensor有两种创建方法,如下: inputs = torch.randn(m, n) new_inputs = inputs.new() new_inputs = torch.Tensor.new(inputs) 三.具体代码 import torch rectangle_height = 1 rectangle_width

  • pytorch中的inference使用实例

    这里inference两个程序的连接,如目标检测,可以利用一个程序提取候选框,然后把候选框输入到分类cnn网络中. 这里常需要进行一定的连接. #加载训练好的分类CNN网络 model=torch.load('model.pkl') #假设proposal_img是我们提取的候选框,是需要输入到CNN网络的数据 #先定义transforms对输入cnn的网络数据进行处理,常包括resize.totensor等操作 data_transforms=transforms.Compose([trans

  • PyTorch中的C++扩展实现

    今天要聊聊用 PyTorch 进行 C++ 扩展. 在正式开始前,我们需要了解 PyTorch 如何自定义module.这其中,最常见的就是在 python 中继承torch.nn.Module,用 PyTorch 中已有的 operator 来组装成自己的模块.这种方式实现简单,但是,计算效率却未必最佳,另外,如果我们想实现的功能过于复杂,可能 PyTorch 中那些已有的函数也没法满足我们的要求.这时,用 C.C++.CUDA 来扩展 PyTorch 的模块就是最佳的选择了. 由于目前市面上

随机推荐