12.3. 自动并行

文章目录

    • 12.3. 自动并行
      • 12.3.1. 基于GPU的并行计算
      • 12.3.2. 并行计算与通信
      • 12.3.3. 小结

12.3. 自动并行

通常情况下单个操作符将使用所有CPU或单个GPU上的所有计算资源。
例如,即使在一台机器上有多个CPU处理器,dot 操作符也将使用所有CPU上的所有核心(和线程)。
这样的行为同样适用于单个GPU。因此,并行化对于单设备计算机来说并不是很有用,而并行化对于多个设备就很重要了。

12.3.1. 基于GPU的并行计算

让我们从定义一个具有参考性的用于测试的工作负载开始:下面的run函数将执行 10次“矩阵-矩阵”乘法时需要使用的数据分配到两个变量(x_gpu1和x_gpu2)中,这两个变量分别位于我们选择的不同设备上。

devices = d2l.try_all_gpus()
def run(x):
    return [x.mm(x) for _ in range(50)]

x_gpu1 = torch.rand(size=(4000, 4000), device=devices[0])
x_gpu2 = torch.rand(size=(4000, 4000), device=devices[1])

# 现在我们使用函数来数据。我们通过在测量之前预热设备(对设备执行一次传递)来确保缓存的作用不影响最终的结果。torch.cuda.synchronize()函数将会等待一个CUDA设备上的所有流中的所有核心的计算完成。函数接受一个device参数,代表是哪个设备需要同步。如果device参数是None(默认值),它将使用current_device()找出的当前设备。
run(x_gpu1)
run(x_gpu2)  # 预热设备
torch.cuda.synchronize(devices[0])
torch.cuda.synchronize(devices[1])

with d2l.Benchmark('GPU1 time'):
    run(x_gpu1)
    torch.cuda.synchronize(devices[0])

with d2l.Benchmark('GPU2 time'):
    run(x_gpu2)
    torch.cuda.synchronize(devices[1])
    
# result
GPU1 time: 0.5036 sec
GPU2 time: 0.5141 sec

# 如果我们删除两个任务之间的synchronize语句,系统就可以在两个设备上自动实现并行计算。
with d2l.Benchmark('GPU1 & GPU2'):
    run(x_gpu1)
    run(x_gpu2)
    torch.cuda.synchronize()

# result
GPU1 & GPU2: 0.5043 sec

在上述情况下,总执行时间小于两个部分执行时间的总和,因为深度学习框架自动调度两个GPU设备上的计算,而不需要用户编写复杂的代码。

12.3.2. 并行计算与通信

在许多情况下,我们需要在不同的设备之间移动数据,比如在CPU和GPU之间,或者在不同的GPU之间。
例如,当我们打算执行分布式优化时,就需要移动数据来聚合多个加速卡上的梯度。
让我们通过在GPU上计算,然后将结果复制回CPU来模拟这个过程。

def copy_to_cpu(x, non_blocking=False):
    return [y.to('cpu', non_blocking=non_blocking) for y in x]

with d2l.Benchmark('在GPU1上运行'):
    y = run(x_gpu1)
    torch.cuda.synchronize()

with d2l.Benchmark('复制到CPU'):
    y_cpu = copy_to_cpu(y)
    torch.cuda.synchronize()
    
# result
在GPU1上运行: 0.5064 sec
复制到CPU: 2.4303 sec

# 在PyTorch中,to()和copy_()等函数都允许显式的non_blocking参数,这允许在不需要同步时调用方可以绕过同步。设置non_blocking=True让我们模拟这个场景。
with d2l.Benchmark('在GPU1上运行并复制到CPU'):
    y = run(x_gpu1)
    y_cpu = copy_to_cpu(y, True)
    torch.cuda.synchronize()

# result
在GPU1上运行并复制到CPU: 1.9874 sec

最后,我们给出了一个简单的两层多层感知机在CPU和两个GPU上训练时的计算图及其依赖关系的例子,如 图12.3.1所示。手动调度由此产生的并行程序将是相当痛苦的。这就是基于图的计算后端进行优化的优势所在。

12.3. 自动并行_第1张图片

在一个CPU和两个GPU上的两层的多层感知机的计算图及其依赖关系

12.3.3. 小结

  • 现代系统拥有多种设备,如多个GPU和多个CPU,还可以并行地、异步地使用它们。

  • 现代系统还拥有各种通信资源,如PCI Express、存储(通常是固态硬盘或网络存储)和网络带宽,为了达到最高效率可以并行使用它们。

  • 后端可以通过自动化地并行计算和通信来提高性能。

你可能感兴趣的:(Python基础学习,python书籍笔记,#,深度学习,人工智能)