Pytorch 在 Google Colaboratory 上的 GPU 性能比 CPU 慢
GPU performing slower than CPU for Pytorch on Google Colaboratory
GPU 训练这个网络大约需要 16 秒。 CPU 大约需要 13 秒。 (我在uncommenting/commenting合适的线路上做测试)。任何人都可以看到我的代码或 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)
我看到你在计时你不应该计时的东西(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
,我们称其为 "cold start"(此笔记本中的 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 notebook 的情况下再次 运行 它:
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
,训练循环 运行s 在 GTX1080 上为 3.5 秒,在 CPU.
上为 85 秒
GPU 训练这个网络大约需要 16 秒。 CPU 大约需要 13 秒。 (我在uncommenting/commenting合适的线路上做测试)。任何人都可以看到我的代码或 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)
我看到你在计时你不应该计时的东西(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
,我们称其为 "cold start"(此笔记本中的 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 notebook 的情况下再次 运行 它:
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
,训练循环 运行s 在 GTX1080 上为 3.5 秒,在 CPU.