【问题标题】:GPU performing slower than CPU for Pytorch on Google Colaboratory在 Google Colaboratory 上,对于 Pytorch,GPU 的性能比 CPU 慢
【发布时间】:2018-12-13 05:13:06
【问题描述】:

GPU 在大约 16 秒内训练这个网络。 CPU 在大约 13 秒内。 (我正在取消注释/注释适当的行以进行测试)。谁能看到我的代码或 pytorch 安装有什么问题? (我已经检查了 GPU 是否可用,并且 GPU 上有足够的可用内存。

from os import path
from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())

accelerator = 'cu80' if path.exists('/opt/bin/nvidia-smi') else 'cpu'
print(accelerator)
!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.0-{platform}-linux_x86_64.whl torchvision
print("done")

#########################

import torch
from datetime import datetime

startTime = datetime.now()

dtype = torch.float
device = torch.device("cpu") # Comment this to run on GPU
# device = torch.device("cuda:0") # Uncomment this to run on GPU

# N is batch size; D_in is input dimension;
# H is hidden dimension; D_out is output dimension.
N, D_in, H, D_out = 64, 1024, 128, 8

# Create random Tensors to hold input and outputs.
x = torch.randn(N, D_in, device=device, dtype=dtype)
t = torch.randn(N, D_out, device=device, dtype=dtype)

# Create random Tensors for weights.
w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
w3 = torch.randn(D_out, D_out, device=device, dtype=dtype, requires_grad=True)

learning_rate = 1e-9
for i in range(10000):
    y_pred = x.mm(w1).clamp(min=0).mm(w2).clamp(min=0).mm(w3)

    loss = (y_pred - t).pow(2).sum()

    if i % 1000 == 0:
        print(i, loss.item())

    loss.backward()

    # Manually update weights using gradient descent
    with torch.no_grad():
        w1 -= learning_rate * w1.grad
        w2 -= learning_rate * w2.grad

        # Manually zero the gradients after updating weights
        w1.grad.zero_()
        w2.grad.zero_()

print(datetime.now() - startTime)

【问题讨论】:

    标签: python pytorch google-colaboratory


    【解决方案1】:

    我看到你正在计时你不应该计时的事情(dtype,设备的定义......)。这里有趣的是输入、输出和权重张量的创建。

    startTime = datetime.now()
    # Create random Tensors to hold input and outputs.
    x = torch.randn(N, D_in, device=device, dtype=dtype)
    t = torch.randn(N, D_out, device=device, dtype=dtype)
    torch.cuda.synchronize()
    print(datetime.now()-startTime)
    
    # Create random Tensors for weights.
    startTime = datetime.now()
    w1 = torch.randn(D_in, H, device=device, dtype=dtype, requires_grad=True)
    w2 = torch.randn(H, D_out, device=device, dtype=dtype, requires_grad=True)
    w3 = torch.randn(D_out, D_out, device=device, dtype=dtype, requires_grad=True)
    torch.cuda.synchronize()
    print(datetime.now()-startTime)
    

    和训练循环

    startTime = datetime.now()
    
    for i in range(10000):
        y_pred = x.mm(w1).clamp(min=0).mm(w2).clamp(min=0).mm(w3)
    
        loss = (y_pred - t).pow(2).sum()
    
        if i % 1000 == 0:
            print(i, loss.item())
    
        loss.backward()
    
        # Manually update weights using gradient descent
        with torch.no_grad():
            w1 -= learning_rate * w1.grad
            w2 -= learning_rate * w2.grad
    
            # Manually zero the gradients after updating weights
            w1.grad.zero_()
            w2.grad.zero_()
    torch.cuda.synchronize()
    print(datetime.now() - startTime)
    

    为什么 GPU 变慢了

    我在我的机器上运行它,GTX1080 和一个非常好的 CPU,所以绝对时序更低,但解释应该仍然有效。如果你打开一个 Jupyter notebook 并在 CPU 上运行它:

    0:00:00.001786 time to create input/output tensors
    0:00:00.003359 time to create weight tensors
    0:00:04.030797 time to run training loop
    

    现在您将设备设置为cuda,我们称之为“冷启动”(之前在此笔记本的 GPU 上没有运行过任何内容)

    0:00:03.180510 time to create input/output tensors
    0:00:00.000642 time to create weight tensors
    0:00:03.534751 time to run training loop
    

    您会看到运行训练循环的时间减少了少量,但有 3 秒的开销,因为您需要将张量从 CPU 移动到 GPU RAM。

    如果在不关闭 Jupyter 笔记本的情况下再次运行它:

    0:00:00.000421 time to create input/output tensors
    0:00:00.000733 time to create weight tensors
    0:00:03.501581 time to run training loop
    

    开销消失了,因为 Pytorch 使用 caching memory allocator 来加快速度。

    您会注意到,您在训练循环中获得的加速非常小,这是因为您正在执行的操作是在非常小的张量上进行的。在处理小型架构和数据时,我总是运行一个快速测试,看看我是否真的通过在 GPU 上运行它获得了什么。 例如,如果我设置N, D_in, H, D_out = 64, 5000, 5000, 8,训练循环在 GTX1080 上运行 3.5 秒,在 CPU 上运行 85 秒。

    【讨论】:

    • 非常感谢,很好的回答,真的很有帮助。通过增加隐藏层中的节点数量,我看到了同样的效果 :)
    • 我将调用添加到torch.cuda.synchronize,因为在使用 GPU 时需要它们来获得正确的时间
    猜你喜欢
    • 2019-04-18
    • 2019-11-06
    • 2019-04-22
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 2021-02-09
    相关资源
    最近更新 更多