# 2.8 将张量转移到GPU上运行

PyTorch张量的最后一点是关于在GPU上计算。每一个Torch张量都可以转移到GPU上去执行快速、大规模并且可以并行的计算。在张量上执行的所有操作均由PyTorch自带的GPU特定例程执行。

> 请注意：
> 截止至2019年初，主要的PyTorch版本仅仅在支持CUDA的GPU上具有加速功能。PyTorch的概念验证版本（Proof-of-concept version）已经可以运行在AMD的[ROCm](https://rocm.github.io)平台上，但是从1.0版开始，尚未将全部支持合并到PyTorch中。对[Google TPU的支持](https://github.com/pytorch/xla)正在进行开发中，目前的概念验证版已在[Google Colab](https://colab.research.google.com)中向公众公开。在我们写这章的时候，并未计划在其他GPU技术（例如OpenCL）上实现相应的数据结构和内核。

除了`dtype`之外，PyTorch张量还具有设备（`device`）的概念，这是在设置计算机上放张量（tensor）数据的位置。 通过为构造函数指定相应的参数，可以在GPU上创建张量：

```python
points_gpu = torch.tensor([[1.0, 4.0], [2.0, 1.0], [3.0, 4.0]], device='cuda')
```

你可以使用`to`方法将在CPU上创建的张量（tensor）复制到GPU：

```python
points_gpu = points.to(device='cuda')
```

这段代码返回一个具有相同数值数据的新张量，但存储在GPU的RAM中，而不是常规的系统RAM中。

现在数据已经存放在本地的GPU中，当在张量上运行数字运算时，你可以看见很好的加速效果。并且，这个新GPU支持的张量的类也更改为`torch.cuda.FloatTensor`（一开始输入的类型为`torch.FloatTensor`；`torch.cuda.DoubleTensor`等等也存在对应关系）。在大部分样例中，基于CPU和GPU的张量都公开面向用户相同的API，这使得与繁琐数字运算过程中无关的代码的编写更加容易。

如果你的机器拥有多个GPU，你可以通过传递从零开始的整数来确定张量分配给哪个GPU，该整数标志着机器上的GPU下标：

```python
points_gpu = points.to(device='cuda:0')
```

此时，在GPU上执行对张量的任何操作，例如将所有元素乘以一个常数。

```python
points = 2 * points # 在CPU上做乘法
points_gpu = 2 * points.to(device='cuda') # 在GPU上做乘法
```

请注意，当计算结果产生后，`points_gpu`的张量并不会返回到CPU。这里发生的是以下三个过程： 

1. 将`points`张量复制到GPU
2. 在GPU上分配了一个新的张量，并用于存储乘法的结果
3. 返回该GPU张量的句柄

因此，如果你还想向结果加上一个常量：

```python
points_gpu = points_gpu + 4
```

加法仍然在GPU上执行，并且没有信息流到CPU（除非您打印或访问得到的张量）。 如果要将张量移回CPU，你需要为`to`方法提供一个cpu参数：

```python
points_cpu = points_gpu.to(device='cpu')
```

你可以使用速记方法`cpu`和`cuda`代替`to`方法来实现相同的目标

```python
points_gpu = points.cuda() # 默认为GPU0
points_gpu = points.cuda(0)
points_cpu = points_gpu.cpu()
```

值得一提的是，使用`to`方法时，可以通过提供`device`和`dtype`参数来同时更改位置和数据类型。