PyTorch中的CUDA的操作方法_第1頁
PyTorch中的CUDA的操作方法_第2頁
PyTorch中的CUDA的操作方法_第3頁
PyTorch中的CUDA的操作方法_第4頁
PyTorch中的CUDA的操作方法_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第PyTorch中的CUDA的操作方法目錄前言一.常見CPU和GPU操作命令二.CPU和GPU設備上的Tensor1.Tensor從CPU拷貝到GPU上2.直接在GPU上創(chuàng)建Tensor3.CUDAStreams三.固定緩沖區(qū)四.自動設備感知1.適配CPU和GPU設備2.模型遷移到GPU設備

前言

CUDA(ComputeUnifiedDeviceArchitecture)是NVIDIA推出的異構計算平臺,PyTorch中有專門的模塊torch.cuda來設置和運行CUDA相關操作。本地安裝環(huán)境為Windows10,Python3.7.8和CUDA11.6,安裝PyTorch最新穩(wěn)定版本1.12.1如下:

pip3installtorchtorchvisiontorchaudio--extra-index-url/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("defaultdevice:{}".format(torch.Tensor([4,5,6]).device))

defaultdevice:cpu

4.查看所有可用的cpu設備的數(shù)量

print("availablecpudevices:{}".format(torch.cuda.os.cpu_count()))

availablecpudevices:20

這里CPU設備數(shù)量指的是邏輯處理器的數(shù)量。

5.查看所有可用的gpu設備的數(shù)量

print("availablegpudevices:{}".format(torch.cuda.device_count()))

availablegpudevices:1

6.獲取gpu設備的名稱

print("gpudevicename:{}".format(torch.cuda.get_device_name(torch.device("cuda:0"))))

gpudevicename:NVIDIAGeForceGTX1080Ti

7.通過device=cpu:0指定cpu:0設備

device=torch.Tensor([1,2,3],device="cpu:0").device

print("devicetype:{}".format(device))

devicetype:cpu

8.通過torch.device指定cpu:0設備

cpu1=torch.device("cpu:0")

print("cpudevice:{}:{}".format(cpu1.type,cpu1.index))

cpudevice:cpu:0

9.使用索引的方式,默認使用CUDA設備

gpu=torch.device(0)

print("gpudevice:{}:{}".format(gpu.type,gpu.index))

gpudevice:cuda:0

10.通過torch.device(cuda:0)指定cuda:0設備

gpu=torch.device("cuda:0")

print("gpudevice:{}:{}".format(gpu.type,gpu.index))

gpudevice:cuda:0

二.CPU和GPU設備上的Tensor

默認情況下創(chuàng)建Tensor是在CPU設備上的,但是可以通過copy_、to、cuda等方法將CPU設備中的Tensor轉移到GPU設備上。當然也是可以直接在GPU設備上創(chuàng)建Tensor的。torch.tensor和torch.Tensor的區(qū)別是,torch.tensor可以通過device指定gpu設備,而torch.Tensor只能在cpu上創(chuàng)建,否則報錯。

1.Tensor從CPU拷貝到GPU上

#默認創(chuàng)建的tensor是在cpu上創(chuàng)建的

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_()方法,實現(xiàn)如下:

defcopy_(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上創(chuàng)建Tensor

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

print(gpu_tensor1.device)

#在gpu設備上創(chuàng)建隨機數(shù)tensor

print(torch.rand((3,4),device=torch.device("cuda:0")))

#在gpu設備上創(chuàng)建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.CUDAStreams

Steam是CUDA命令線性執(zhí)行的抽象形式,分配給設備的CUDA命令按照入隊序列的順序執(zhí)行。每個設備都有一個默認的Steam,也可以通過torch.cuda.Stream()創(chuàng)建新的Stream。如果不同Stream中的命令交互執(zhí)行,那么就不能保證命令絕對按順序執(zhí)行。下面的這個例子不同的Stream就可能會產生錯誤。

cuda=torch.device("cuda")

#創(chuàng)建默認的stream,A就是使用的默認stream

s=torch.cuda.Stream()

A=torch.randn((1,10),device=cuda)

foriinrange(100):

#在新的stream上對默認的stream上創(chuàng)建的tensor進行求和

withtorch.cuda.stream(s):

#存在的問題是:torch.sum()可能會在torch.randn()之前執(zhí)行

B=torch.sum(A)

print(B)

這個例子存在的問題是torch.sum()可能會在torch.randn()之前就執(zhí)行。為了保證Stream中的命令絕對按順序執(zhí)行,接下來使用Synchronize同步方法解決上面例子的問題:

cuda=torch.device("cuda")

s=torch.cuda.Stream()

A=torch.randn((1,10),device=cuda)

default_stream=torch.cuda.current_stream()

print("DefaultStream:{}".format(default_stream))

#等待創(chuàng)建A的stream執(zhí)行完畢

torch.cuda.Stream.synchronize(default_stream)

foriinrange(100):

#在新的stream上對默認的stream上創(chuàng)建的tensor進行求和

withtorch.cuda.stream(s):

print("currentstream:{}".format(torch.cuda.current_stream()))

B=torch.sum(A)

print(B)

解決問題的思路就是通過torch.cuda.Stream.synchronize(default_stream)等待創(chuàng)建A的stream執(zhí)行完畢,然后再執(zhí)行新的Stream中的指令。

除此之外,使用memory_cached方法獲取緩存內存的大小,使用max_memory_cached方法獲取最大緩存內存的大小,使用max_memory_allocated方法獲取最大分配內存的大小??梢允褂胑mpty_cache方法釋放無用的緩存內存。

三.固定緩沖區(qū)

緩存就是當計算機內存不足的時候,就會把內存中的數(shù)據存儲到硬盤上。固定緩沖區(qū)就是說常駐內存,不能把這部分數(shù)據緩存到硬盤上。可以直接使用pin_memory方法或在Tensor上直接調用pin_memory方法將Tensor復制到固定緩沖區(qū)。為什么要做固定緩沖區(qū)呢?目的只有一個,就是把CPU上的固定緩沖區(qū)拷貝到GPU上時速度快。Tensor上的is_pinned方法可以查看該Tensor是否加載到固定緩沖區(qū)中。

fromtorch.utils.data._utils.pin_memoryimportpin_memory

x=torch.Tensor([[1,2,4],[5,7,9],[3,7,10]])

#通過pin_memory()方法將x復制到固定緩沖區(qū)

y=pin_memory(x)

#在tensor上直接調用pin_memory()方法將tensor復制到固定緩沖區(qū)

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放入固定緩沖區(qū)后,就可以異步將數(shù)據復制到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.dev

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論