Skip to content

Commit

Permalink
NVIDIA, gpu memory term fix
Browse files Browse the repository at this point in the history
  • Loading branch information
astonzhang committed Dec 27, 2018
1 parent 3793aac commit 729af01
Show file tree
Hide file tree
Showing 10 changed files with 35 additions and 35 deletions.
2 changes: 1 addition & 1 deletion chapter_appendix/aws.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ ssh -i "/path/to/key.pem" ubuntu@ec2-xx-xxx-xxx-xxx.y.compute.amazonaws.com
sudo apt-get update && sudo apt-get install -y build-essential git libgfortran3
```

Nvidia一般每年会更新一次CUDA主版本。这里我们下载作者写本书时的最新主版本CUDA 9.0(也可使用MXNet支持的其他版本)。访问Nvidia官网https://developer.nvidia.com/cuda-90-download-archive )获取正确版本的CUDA 9.0的下载地址,如图11.17所示。
NVIDIA一般每年会更新一次CUDA主版本。这里我们下载作者写本书时的最新主版本CUDA 9.0(也可使用MXNet支持的其他版本)。访问NVIDIA官网https://developer.nvidia.com/cuda-90-download-archive )获取正确版本的CUDA 9.0的下载地址,如图11.17所示。

![获取CUDA9.0的下载地址。](../img/cuda.png)

Expand Down
14 changes: 7 additions & 7 deletions chapter_appendix/buy-gpu.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

## 选择GPU

目前独立GPU主要有AMD和NVIDIA两家厂商。其中NVIDIA在深度学习布局较早,对深度学习框架支持更好。因此,目前大家主要会选择NVIDIA的GPU。
目前独立显卡主要有AMD和NVIDIA两家厂商。其中NVIDIA在深度学习布局较早,对深度学习框架支持更好。因此,目前大家主要会选择NVIDIA的GPU。

NVIDIA有面向个人用户(例如GTX系列)和企业用户(例如Tesla系列)的两类GPU。这两类GPU的计算能力相当。然而,面向企业用户的GPU通常使用被动散热并增加了内存校验,从而更适合数据中心,并通常要比面向个人用户的GPU贵上10倍。
NVIDIA有面向个人用户(例如GTX系列)和企业用户(例如Tesla系列)的两类GPU。这两类GPU的计算能力相当。然而,面向企业用户的GPU通常使用被动散热并增加了显存校验,从而更适合数据中心,并通常要比面向个人用户的GPU贵上10倍。

如果你是拥有100台机器以上的大公司用户,通常可以考虑针对企业用户的NVIDIA Tesla系列。如果你是拥有10到100台机器的实验室和中小公司用户,预算充足的情况下可以考虑NVIDIA DGX系列,否则可以考虑购买如Supermicro之类的性价比比较高的服务器,然后再购买安装GTX系列的GPU。

Expand All @@ -15,10 +15,10 @@ NVIDIA一般每一两年发布一次新版本的GPU,例如2016年发布的是G
GPU的性能主要由以下三个参数构成:

1. 计算能力。通常我们关心的是32位浮点计算能力。16位浮点训练也开始流行,如果只做预测的话也可以用8位整数。
2. 显存大小。当模型越大,或者训练时的批量越大时,所需要的GPU内存就越多
3. 显存带宽。只有当内存带宽足够时才能充分发挥计算能力
2. 显存大小。当模型越大,或者训练时的批量越大时,所需要的显存就越多
3. 显存带宽。只有当显存带宽足够时才能充分发挥计算能力

对于大部分用户来说,只要考虑计算能力就可以了。GPU内存尽量不小于4GB。但如果GPU要同时显示图形界面,那么推荐的内存大小至少为6GB。内存带宽通常相对固定,选择空间较小。
对于大部分用户来说,只要考虑计算能力就可以了。显存尽量不小于4GB。但如果GPU要同时显示图形界面,那么推荐的显存大小至少为6GB。显存带宽通常相对固定,选择空间较小。

图11.19描绘了GTX 900和1000系列里各个型号的32位浮点计算能力和价格的对比。其中价格为Wikipedia的建议价格。

Expand All @@ -36,9 +36,9 @@ GPU的性能主要由以下三个参数构成:

通常,我们主要用GPU做深度学习训练。因此,不需要购买高端的CPU。至于整机配置,尽量参考网上推荐的中高档的配置就好。不过,考虑到GPU的功耗、散热和体积,我们在整机配置上也需要考虑以下三个额外因素。

1. 机箱体积。GPU尺寸较大,通常考虑较大且自带风扇的机箱。
1. 机箱体积。显卡尺寸较大,通常考虑较大且自带风扇的机箱。
2. 电源。购买GPU时需要查一下GPU的功耗,例如50W到300W不等。购买电源要确保功率足够,且不会过载机房的供电。
3. 主板的PCIe卡槽。推荐使用PCIe 3.0 16x来保证充足的GPU到主内存的带宽。如果搭载多块GPU,要仔细阅读主板说明,以确保多块GPU一起使用时仍然是16x带宽。注意,有些主板搭载4块GPU时会降到8x甚至4x带宽。
3. 主板的PCIe卡槽。推荐使用PCIe 3.0 16x来保证充足的GPU到内存的带宽。如果搭载多块GPU,要仔细阅读主板说明,以确保多块GPU一起使用时仍然是16x带宽。注意,有些主板搭载4块GPU时会降到8x甚至4x带宽。


## 小结
Expand Down
2 changes: 1 addition & 1 deletion chapter_computational-performance/multiple-gpus.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 多GPU计算

本节中我们将展示如何使用多个GPU计算,例如使用多个GPU训练同一个模型。正如你期望的那样,运行本节中的程序需要至少两块GPU。事实上,一台机器上安装多块GPU很常见,这是因为主板上通常会有多个PCIe插槽。如果正确安装了Nvidia驱动,我们可以通过`nvidia-smi`命令来查看当前计算机上的全部GPU。
本节中我们将展示如何使用多个GPU计算,例如使用多个GPU训练同一个模型。正如你期望的那样,运行本节中的程序需要至少两块GPU。事实上,一台机器上安装多块GPU很常见,这是因为主板上通常会有多个PCIe插槽。如果正确安装了NVIDIA驱动,我们可以通过`nvidia-smi`命令来查看当前计算机上的全部GPU。

```{.python .input n=1}
!nvidia-smi
Expand Down
4 changes: 2 additions & 2 deletions chapter_convolutional-neural-networks/alexnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ AlexNet与LeNet的设计理念非常相似,但也有显著的区别。

AlexNet第一层中的卷积窗口形状是$11\times11$。因为ImageNet中绝大多数图像的高和宽均比MNIST图像的高和宽大十倍以上,ImageNet图像的物体占用更多的像素,所以需要更大的卷积窗口来捕获物体。第二层中的卷积窗口形状减小到$5\times5$,之后全采用$3\times3$。此外,第一、第二和第五个卷积层之后都使用了窗口形状为$3\times3$、步幅为2的最大池化层。而且,AlexNet使用的卷积通道数也数十倍大于LeNet中的卷积通道数。

紧接着最后一个卷积层的是两个输出个数为4096的全连接层。这两个巨大的全连接层带来将近1GB的模型参数。由于早期GPU显存的限制,最早的AlexNet使用双数据流的设计使得一个GPU只需要处理一半模型。幸运的是GPU内存在过去几年得到了长足的发展,通常我们不再需要这样的特别设计了。
紧接着最后一个卷积层的是两个输出个数为4096的全连接层。这两个巨大的全连接层带来将近1GB的模型参数。由于早期显存的限制,最早的AlexNet使用双数据流的设计使得一个GPU只需要处理一半模型。幸运的是显存在过去几年得到了长足的发展,通常我们不再需要这样的特别设计了。

第二,AlexNet将sigmoid激活函数改成了更加简单的ReLU激活函数。一方面,ReLU激活函数的计算更简单,例如它并没有sigmoid激活函数中的求幂运算。另一方面,ReLU激活函数在不同的参数初始化方法下使模型更容易训练。这是由于当sigmoid激活函数输出极接近0或1时,这些区域的梯度几乎为0,从而造成反向传播无法继续更新部分模型参数;而ReLU激活函数在正区间的梯度恒为1。因此,如模型参数初始化不当,sigmoid函数可能在正区间得到几乎为0的梯度,从而令模型无法得到有效训练。

Expand Down Expand Up @@ -141,7 +141,7 @@ gb.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs)

* 尝试增加迭代周期。跟LeNet相比,结果有什么区别?为什么?
* AlexNet对于Fashion-MNIST数据集来说可能过于复杂。试着简化模型来使得训练更快,同时保证准确率不明显下降。
* 修改批量大小,观察准确率和GPU内存的变化
* 修改批量大小,观察准确率和显存的变化


## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/1258)
Expand Down
2 changes: 1 addition & 1 deletion chapter_convolutional-neural-networks/densenet.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ gb.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs)
## 练习

* DenseNet论文中提到的一个优点是模型参数比ResNet的更小,这是为什么?
* DenseNet被人诟病的一个问题是内存消耗过多。真的会这样吗?可以把输入形状换成$224\times 224$,来看看实际(GPU)内存消耗
* DenseNet被人诟病的一个问题是存储空间消耗过多。真的会这样吗?可以把输入形状换成$224\times 224$,来看看实际的消耗
* 实现DenseNet论文中的表1提出的各个DenseNet版本 [1]

## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/1664)
Expand Down
6 changes: 3 additions & 3 deletions chapter_convolutional-neural-networks/lenet.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,21 @@ ctx = try_gpu()
ctx
```

相应地,我们对[“Softmax回归的从零开始实现”](../chapter_deep-learning-basics/softmax-regression-scratch.md)一节中描述的`evaluate_accuracy`函数略作修改。由于数据刚开始存在CPU的内存上,当`ctx`变量为GPU时,我们通过[“GPU计算”](../chapter_deep-learning-computation/use-gpu.md)一节中介绍的`as_in_context`函数将数据复制到GPU上,例如`gpu(0)`
相应地,我们对[“Softmax回归的从零开始实现”](../chapter_deep-learning-basics/softmax-regression-scratch.md)一节中描述的`evaluate_accuracy`函数略作修改。由于数据刚开始存在CPU使用的内存上,当`ctx`变量代表GPU及相应的显存时,我们通过[“GPU计算”](../chapter_deep-learning-computation/use-gpu.md)一节中介绍的`as_in_context`函数将数据复制到显存上,例如`gpu(0)`

```{.python .input}
# 本函数已保存在 gluonbook 包中方便以后使用。该函数将被逐步改进:它的完整实现将在“图像增
# 广”一节中描述。
def evaluate_accuracy(data_iter, net, ctx):
acc = nd.array([0], ctx=ctx)
for X, y in data_iter:
# 如果 ctx GPU,将数据复制到 GPU 上
# 如果 ctx 代表 GPU 及相应的显存,将数据复制到显存上
X, y = X.as_in_context(ctx), y.as_in_context(ctx)
acc += gb.accuracy(net(X), y)
return acc.asscalar() / len(data_iter)
```

我们同样对[“Softmax回归的从零开始实现”](../chapter_deep-learning-basics/softmax-regression-scratch.md)一节中定义的`train_ch3`函数略作修改,确保计算使用的数据和模型同在CPU或GPU的内存上
我们同样对[“Softmax回归的从零开始实现”](../chapter_deep-learning-basics/softmax-regression-scratch.md)一节中定义的`train_ch3`函数略作修改,确保计算使用的数据和模型同在内存或显存上

```{.python .input}
# 本函数已保存在 gluonbook 包中方便以后使用。
Expand Down
2 changes: 1 addition & 1 deletion chapter_convolutional-neural-networks/vgg.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ gb.train_ch5(net, train_iter, test_iter, batch_size, trainer, ctx, num_epochs)

## 练习

* 与AlexNet相比,VGG的计算慢很多,也需要很多的GPU内存。试分析原因。
* 与AlexNet相比,VGG的计算慢很多,也需要很多的内存或显存。试分析原因。
* 尝试将Fashion-MNIST中图像的高和宽由224改为96。这在实验中有哪些影响?
* 参考VGG论文里的表1来构造VGG其他常用模型,例如VGG-16和VGG-19 [1]

Expand Down
30 changes: 15 additions & 15 deletions chapter_deep-learning-computation/use-gpu.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GPU计算

目前为止我们一直在使用CPU计算。对于复杂的神经网络和大规模的数据来说,使用CPU来计算可能不够高效。本节中,我们将介绍如何使用单块Nvidia GPU来计算。首先,需要确保已经安装好了至少一块Nvidia GPU。然后,下载CUDA并按照提示设置好相应的路径 [1]。这些准备工作都完成后,下面就可以通过`nvidia-smi`命令来查看显卡信息了。
目前为止我们一直在使用CPU计算。对于复杂的神经网络和大规模的数据来说,使用CPU来计算可能不够高效。本节中,我们将介绍如何使用单块NVIDIA GPU来计算。首先,需要确保已经安装好了至少一块NVIDIA GPU。然后,下载CUDA并按照提示设置好相应的路径 [1]。这些准备工作都完成后,下面就可以通过`nvidia-smi`命令来查看显卡信息了。

```{.python .input n=1}
!nvidia-smi
Expand All @@ -10,7 +10,7 @@

## 计算设备

MXNet可以指定用来存储和计算的设备,例如CPU或者GPU。默认情况下,MXNet会将数据创建在主内存,然后利用CPU来计算。在MXNet中,CPU和GPU可分别由`cpu()``gpu()`来表示。需要注意的是,`mx.cpu()`(或者在括号里填任意整数)表示所有的物理CPU和内存。这意味着MXNet的计算会尽量使用所有的CPU核。但`mx.gpu()`只代表一块显卡和相应的显卡内存。如果有多块GPU,我们用`mx.gpu(i)`来表示第$i$块GPU($i$从0开始)且`mx.gpu(0)``mx.gpu()`等价。
MXNet可以指定用来存储和计算的设备,例如使用内存的CPU或者使用显存的GPU。默认情况下,MXNet会将数据创建在内存,然后利用CPU来计算。在MXNet中,`mx.cpu()`(或者在括号里填任意整数)表示所有的物理CPU和内存。这意味着MXNet的计算会尽量使用所有的CPU核。但`mx.gpu()`只代表一块GPU和相应的显存。如果有多块GPU,我们用`mx.gpu(i)`来表示第$i$块GPU及相应的显存($i$从0开始)且`mx.gpu(0)``mx.gpu()`等价。

```{.python .input}
import mxnet as mx
Expand All @@ -22,7 +22,7 @@ mx.cpu(), mx.gpu(), mx.gpu(1)

## NDArray的GPU计算

默认情况下,NDArray存在CPU上。因此,之前我们每次打印NDArray的时候都会看到`@cpu(0)`这个标识。
默认情况下,NDArray存在内存上。因此,之前我们每次打印NDArray的时候都会看到`@cpu(0)`这个标识。

```{.python .input n=4}
x = nd.array([1, 2, 3])
Expand All @@ -37,7 +37,7 @@ x.context

### GPU上的存储

我们有多种方法将NDArray存储在GPU上。例如我们可以在创建NDArray的时候通过`ctx`参数指定存储设备。下面我们将NDArray变量`a`创建在`gpu(0)`上。注意到在打印`a`时,设备信息变成了`@gpu(0)`创建在GPU上的NDArray只消耗相同GPU的内存。我们可以通过`nvidia-smi`命令查看GPU内存的使用情况。通常,我们需要确保不创建超过GPU内存上限的数据
我们有多种方法将NDArray存储在显存上。例如我们可以在创建NDArray的时候通过`ctx`参数指定存储设备。下面我们将NDArray变量`a`创建在`gpu(0)`上。注意到在打印`a`时,设备信息变成了`@gpu(0)`创建在显存上的NDArray只消耗同一块显卡的显存。我们可以通过`nvidia-smi`命令查看显存的使用情况。通常,我们需要确保不创建超过显存上限的数据

```{.python .input n=5}
a = nd.array([1, 2, 3], ctx=mx.gpu())
Expand All @@ -51,7 +51,7 @@ B = nd.random.uniform(shape=(2, 3), ctx=mx.gpu(1))
B
```

除了在创建时指定,我们也可以通过`copyto``as_in_context`函数在设备之间传输数据。下面我们将CPU上的NDArray变量`x`复制到`gpu(0)`上。
除了在创建时指定,我们也可以通过`copyto``as_in_context`函数在设备之间传输数据。下面我们将内存上的NDArray变量`x`复制到`gpu(0)`上。

```{.python .input n=7}
y = x.copyto(mx.gpu())
Expand All @@ -63,58 +63,58 @@ z = x.as_in_context(mx.gpu())
z
```

需要区分的是,如果源变量和目标变量的`context`一致,`as_in_context`函数使目标变量和源变量共享源变量的内存,
需要区分的是,如果源变量和目标变量的`context`一致,`as_in_context`函数使目标变量和源变量共享源变量的内存或显存。

```{.python .input n=8}
y.as_in_context(mx.gpu()) is y
```

`copyto`函数总是为目标变量创建新的内存
`copyto`函数总是为目标变量开新的内存或显存

```{.python .input}
y.copyto(mx.gpu()) is y
```

### GPU上的计算

MXNet的计算会在数据的`context`所指定的设备上执行。为了使用GPU计算,我们只需要事先将数据存储在GPU上。计算结果会自动保存在相同的GPU上
MXNet的计算会在数据的`context`所指定的设备上执行。为了使用GPU计算,我们只需要事先将数据存储在显存上。计算结果会自动保存在同一块显卡的显存上

```{.python .input n=9}
(z + 2).exp() * y
```

注意,MXNet要求计算的所有输入数据都在CPU或同一个GPU上。这个设计的原因是CPU和不同的GPU之间的数据交互通常比较耗时。因此,MXNet希望用户确切地指明计算的输入数据都在CPU或同一个GPU上。例如,如果将CPU上的NDArray变量`x`和GPU上的NDArray变量`y`做运算,会出现错误信息。当我们打印NDArray或将NDArray转换成NumPy格式时,如果数据不在主内存里,MXNet会将它先复制到主内存,从而造成额外的传输开销。
注意,MXNet要求计算的所有输入数据都在内存或同一块显卡的显存上。这样设计的原因是CPU和不同的GPU之间的数据交互通常比较耗时。因此,MXNet希望用户确切地指明计算的输入数据都在内存或同一块显卡的显存上。例如,如果将内存上的NDArray变量`x`和显存上的NDArray变量`y`做运算,会出现错误信息。当我们打印NDArray或将NDArray转换成NumPy格式时,如果数据不在内存,MXNet会将它先复制到内存,从而造成额外的传输开销。

## Gluon的GPU计算

同NDArray类似,Gluon的模型可以在初始化时通过`ctx`参数指定设备。下面代码将模型参数初始化在GPU上
同NDArray类似,Gluon的模型可以在初始化时通过`ctx`参数指定设备。下面代码将模型参数初始化在显存上

```{.python .input n=12}
net = nn.Sequential()
net.add(nn.Dense(1))
net.initialize(ctx=mx.gpu())
```

当输入是GPU上的NDArray时,Gluon会在相同的GPU上计算结果
当输入是显存上的NDArray时,Gluon会在≈上计算结果

```{.python .input n=13}
net(y)
```

下面我们确认一下模型参数存储在相同的GPU上
下面我们确认一下模型参数存储在同一块显卡的显存上

```{.python .input n=14}
net[0].weight.data()
```

## 小结

* MXNet可以指定用来存储和计算的设备,例如CPU或者GPU。默认情况下,MXNet会将数据创建在主内存,然后利用CPU来计算。
* MXNet要求计算的所有输入数据都在CPU或同一个GPU上
* MXNet可以指定用来存储和计算的设备,如使用内存的CPU或者使用显存的GPU。默认情况下,MXNet会将数据创建在内存,然后利用CPU来计算。
* MXNet要求计算的所有输入数据都在内存或同一块显卡的显存上

## 练习

* 试试大一点的计算任务,例如大矩阵的乘法,看看CPU和GPU的速度区别。如果是计算量很小的任务呢?
* 试试大一点的计算任务,例如大矩阵的乘法,看看使用CPU和GPU的速度区别。如果是计算量很小的任务呢?
* GPU上应如何读写模型参数?

## 扫码直达[讨论区](https://discuss.gluon.ai/t/topic/988)
Expand Down
Loading

0 comments on commit 729af01

Please sign in to comment.