# 4.6 GPU計算
到目前為止,我們一直在使用CPU計算。對復雜的神經網絡和大規模的數據來說,使用CPU來計算可能不夠高效。在本節中,我們將介紹如何使用單塊NVIDIA GPU來計算。所以需要確保已經安裝好了PyTorch GPU版本。準備工作都完成后,下面就可以通過`nvidia-smi`命令來查看顯卡信息了。
``` python
!nvidia-smi # 對Linux/macOS用戶有效
```
輸出:
```
Sun Mar 17 14:59:57 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.48 Driver Version: 390.48 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 GeForce GTX 1050 Off | 00000000:01:00.0 Off | N/A |
| 20% 36C P5 N/A / 75W | 1223MiB / 2000MiB | 0% Default |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: GPU Memory |
| GPU PID Type Process name Usage |
|=============================================================================|
| 0 1235 G /usr/lib/xorg/Xorg 434MiB |
| 0 2095 G compiz 163MiB |
| 0 2660 G /opt/teamviewer/tv_bin/TeamViewer 5MiB |
| 0 4166 G /proc/self/exe 416MiB |
| 0 13274 C /home/tss/anaconda3/bin/python 191MiB |
+-----------------------------------------------------------------------------+
```
可以看到我這里只有一塊GTX 1050,顯存一共只有2000M(太慘了??)。
## 4.6.1 計算設備
PyTorch可以指定用來存儲和計算的設備,如使用內存的CPU或者使用顯存的GPU。默認情況下,PyTorch會將數據創建在內存,然后利用CPU來計算。
用`torch.cuda.is_available()`查看GPU是否可用:
``` python
import torch
from torch import nn
torch.cuda.is_available() # 輸出 True
```
查看GPU數量:
``` python
torch.cuda.device_count() # 輸出 1
```
查看當前GPU索引號,索引號從0開始:
``` python
torch.cuda.current_device() # 輸出 0
```
根據索引號查看GPU名字:
``` python
torch.cuda.get_device_name(0) # 輸出 'GeForce GTX 1050'
```
## 4.6.2 `Tensor`的GPU計算
默認情況下,`Tensor`會被存在內存上。因此,之前我們每次打印`Tensor`的時候看不到GPU相關標識。
``` python
x = torch.tensor([1, 2, 3])
x
```
輸出:
```
tensor([1, 2, 3])
```
使用`.cuda()`可以將CPU上的`Tensor`轉換(復制)到GPU上。如果有多塊GPU,我們用`.cuda(i)`來表示第 $i$ 塊GPU及相應的顯存(`$ i $`從0開始)且`cuda(0)`和`cuda()`等價。
``` python
x = x.cuda(0)
x
```
輸出:
```
tensor([1, 2, 3], device='cuda:0')
```
我們可以通過`Tensor`的`device`屬性來查看該`Tensor`所在的設備。
```python
x.device
```
輸出:
```
device(type='cuda', index=0)
```
我們可以直接在創建的時候就指定設備。
``` python
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
x = torch.tensor([1, 2, 3], device=device)
# or
x = torch.tensor([1, 2, 3]).to(device)
x
```
輸出:
```
tensor([1, 2, 3], device='cuda:0')
```
如果對在GPU上的數據進行運算,那么結果還是存放在GPU上。
``` python
y = x**2
y
```
輸出:
```
tensor([1, 4, 9], device='cuda:0')
```
需要注意的是,存儲在不同位置中的數據是不可以直接進行計算的。即存放在CPU上的數據不可以直接與存放在GPU上的數據進行運算,位于不同GPU上的數據也是不能直接進行計算的。
``` python
z = y + x.cpu()
```
會報錯:
```
RuntimeError: Expected object of type torch.cuda.LongTensor but found type torch.LongTensor for argument #3 'other'
```
## 4.6.3 模型的GPU計算
同`Tensor`類似,PyTorch模型也可以通過`.cuda`轉換到GPU上。我們可以通過檢查模型的參數的`device`屬性來查看存放模型的設備。
``` python
net = nn.Linear(3, 1)
list(net.parameters())[0].device
```
輸出:
```
device(type='cpu')
```
可見模型在CPU上,將其轉換到GPU上:
``` python
net.cuda()
list(net.parameters())[0].device
```
輸出:
```
device(type='cuda', index=0)
```
同樣的,我么需要保證模型輸入的`Tensor`和模型都在同一設備上,否則會報錯。
``` python
x = torch.rand(2,3).cuda()
net(x)
```
輸出:
```
tensor([[-0.5800],
[-0.2995]], device='cuda:0', grad_fn=<ThAddmmBackward>)
```
## 小結
* PyTorch可以指定用來存儲和計算的設備,如使用內存的CPU或者使用顯存的GPU。在默認情況下,PyTorch會將數據創建在內存,然后利用CPU來計算。
* PyTorch要求計算的所有輸入數據都在內存或同一塊顯卡的顯存上。
-----------
> 注:本節與原書此節有一些不同,[原書傳送門](https://zh.d2l.ai/chapter_deep-learning-computation/use-gpu.html)
- Home
- Introduce
- 1.深度學習簡介
- 深度學習簡介
- 2.預備知識
- 2.1環境配置
- 2.2數據操作
- 2.3自動求梯度
- 3.深度學習基礎
- 3.1 線性回歸
- 3.2 線性回歸的從零開始實現
- 3.3 線性回歸的簡潔實現
- 3.4 softmax回歸
- 3.5 圖像分類數據集(Fashion-MINST)
- 3.6 softmax回歸的從零開始實現
- 3.7 softmax回歸的簡潔實現
- 3.8 多層感知機
- 3.9 多層感知機的從零開始實現
- 3.10 多層感知機的簡潔實現
- 3.11 模型選擇、反向傳播和計算圖
- 3.12 權重衰減
- 3.13 丟棄法
- 3.14 正向傳播、反向傳播和計算圖
- 3.15 數值穩定性和模型初始化
- 3.16 實戰kaggle比賽:房價預測
- 4 深度學習計算
- 4.1 模型構造
- 4.2 模型參數的訪問、初始化和共享
- 4.3 模型參數的延后初始化
- 4.4 自定義層
- 4.5 讀取和存儲
- 4.6 GPU計算
- 5 卷積神經網絡
- 5.1 二維卷積層
- 5.2 填充和步幅
- 5.3 多輸入通道和多輸出通道
- 5.4 池化層
- 5.5 卷積神經網絡(LeNet)
- 5.6 深度卷積神經網絡(AlexNet)
- 5.7 使用重復元素的網絡(VGG)
- 5.8 網絡中的網絡(NiN)
- 5.9 含并行連結的網絡(GoogLeNet)
- 5.10 批量歸一化
- 5.11 殘差網絡(ResNet)
- 5.12 稠密連接網絡(DenseNet)
- 6 循環神經網絡
- 6.1 語言模型
- 6.2 循環神經網絡
- 6.3 語言模型數據集(周杰倫專輯歌詞)
- 6.4 循環神經網絡的從零開始實現
- 6.5 循環神經網絡的簡單實現
- 6.6 通過時間反向傳播
- 6.7 門控循環單元(GRU)
- 6.8 長短期記憶(LSTM)
- 6.9 深度循環神經網絡
- 6.10 雙向循環神經網絡
- 7 優化算法
- 7.1 優化與深度學習
- 7.2 梯度下降和隨機梯度下降
- 7.3 小批量隨機梯度下降
- 7.4 動量法
- 7.5 AdaGrad算法
- 7.6 RMSProp算法
- 7.7 AdaDelta
- 7.8 Adam算法
- 8 計算性能
- 8.1 命令式和符號式混合編程
- 8.2 異步計算
- 8.3 自動并行計算
- 8.4 多GPU計算
- 9 計算機視覺
- 9.1 圖像增廣
- 9.2 微調
- 9.3 目標檢測和邊界框
- 9.4 錨框
- 10 自然語言處理
- 10.1 詞嵌入(word2vec)
- 10.2 近似訓練
- 10.3 word2vec實現
- 10.4 子詞嵌入(fastText)
- 10.5 全局向量的詞嵌入(Glove)
- 10.6 求近義詞和類比詞
- 10.7 文本情感分類:使用循環神經網絡
- 10.8 文本情感分類:使用卷積網絡
- 10.9 編碼器--解碼器(seq2seq)
- 10.10 束搜索
- 10.11 注意力機制
- 10.12 機器翻譯