为什么使用 GPU 比使用 CPU 慢?
Why is using the GPU slower than using the CPU?
考虑以下网络:
%%time
import torch
from torch.autograd import grad
import torch.nn as nn
import torch.optim as optim
class net_x(nn.Module):
def __init__(self):
super(net_x, self).__init__()
self.fc1=nn.Linear(1, 20)
self.fc2=nn.Linear(20, 20)
self.out=nn.Linear(20, 400) #a,b,c,d
def forward(self, x):
x=torch.tanh(self.fc1(x))
x=torch.tanh(self.fc2(x))
x=self.out(x)
return x
nx = net_x()
#input
val = 100
t = torch.rand(val, requires_grad = True) #input vector
t = torch.reshape(t, (val,1)) #reshape for batch
#method
dx = torch.autograd.functional.jacobian(lambda t_: nx(t_), t)
这输出
CPU times: user 11.1 s, sys: 3.52 ms, total: 11.1 s
Wall time: 11.1 s
然而,当我改为使用 GPU 时 .to(device)
:
%%time
import torch
from torch.autograd import grad
import torch.nn as nn
import torch.optim as optim
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
class net_x(nn.Module):
def __init__(self):
super(net_x, self).__init__()
self.fc1=nn.Linear(1, 20)
self.fc2=nn.Linear(20, 20)
self.out=nn.Linear(20, 400) #a,b,c,d
def forward(self, x):
x=torch.tanh(self.fc1(x))
x=torch.tanh(self.fc2(x))
x=self.out(x)
return x
nx = net_x()
nx.to(device)
#input
val = 100
t = torch.rand(val, requires_grad = True) #input vector
t = torch.reshape(t, (val,1)).to(device) #reshape for batch
#method
dx = torch.autograd.functional.jacobian(lambda t_: nx(t_), t)
这输出:
CPU times: user 18.6 s, sys: 1.5 s, total: 20.1 s
Wall time: 19.5 s
更新 1:
检查将输入和模型移动到设备的过程的时间安排:
%%time
nx.to(device)
t.to(device)
这输出:
CPU times: user 2.05 ms, sys: 0 ns, total: 2.05 ms
Wall time: 2.13 ms
更新二:
看起来@Gulzar 是对的。我将批量大小更改为 1000 (val=1000
) 并且 CPU 输出:
Wall time: 8min 44s
当 GPU 输出时:
Wall time: 3min 12s
挥手回答
GPU 是“较弱”的计算机,计算核心比 CPU 多得多。
数据必须以“昂贵”的方式从 RAM 内存传递给他们,每隔一段时间,这样他们就可以处理它。
如果数据“大”,并且可以对该数据进行并行处理,则计算速度可能会更快。
如果数据“不够大”,传输数据的成本,或使用较弱内核并同步它们的成本可能会超过并行化的好处。
GPU什么时候有用?
- 对于更大的网络,或更重的计算,例如卷积,或更大的全连接层(更大的矩阵乘法)
- 对于较大的批次 - 批次是并行计算的一种非常简单的方法,因为它们(几乎*)是独立的。 *几乎,因为它们确实需要在某些时候以编程方式同步。
考虑以下网络:
%%time
import torch
from torch.autograd import grad
import torch.nn as nn
import torch.optim as optim
class net_x(nn.Module):
def __init__(self):
super(net_x, self).__init__()
self.fc1=nn.Linear(1, 20)
self.fc2=nn.Linear(20, 20)
self.out=nn.Linear(20, 400) #a,b,c,d
def forward(self, x):
x=torch.tanh(self.fc1(x))
x=torch.tanh(self.fc2(x))
x=self.out(x)
return x
nx = net_x()
#input
val = 100
t = torch.rand(val, requires_grad = True) #input vector
t = torch.reshape(t, (val,1)) #reshape for batch
#method
dx = torch.autograd.functional.jacobian(lambda t_: nx(t_), t)
这输出
CPU times: user 11.1 s, sys: 3.52 ms, total: 11.1 s
Wall time: 11.1 s
然而,当我改为使用 GPU 时 .to(device)
:
%%time
import torch
from torch.autograd import grad
import torch.nn as nn
import torch.optim as optim
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
class net_x(nn.Module):
def __init__(self):
super(net_x, self).__init__()
self.fc1=nn.Linear(1, 20)
self.fc2=nn.Linear(20, 20)
self.out=nn.Linear(20, 400) #a,b,c,d
def forward(self, x):
x=torch.tanh(self.fc1(x))
x=torch.tanh(self.fc2(x))
x=self.out(x)
return x
nx = net_x()
nx.to(device)
#input
val = 100
t = torch.rand(val, requires_grad = True) #input vector
t = torch.reshape(t, (val,1)).to(device) #reshape for batch
#method
dx = torch.autograd.functional.jacobian(lambda t_: nx(t_), t)
这输出:
CPU times: user 18.6 s, sys: 1.5 s, total: 20.1 s
Wall time: 19.5 s
更新 1: 检查将输入和模型移动到设备的过程的时间安排:
%%time
nx.to(device)
t.to(device)
这输出:
CPU times: user 2.05 ms, sys: 0 ns, total: 2.05 ms
Wall time: 2.13 ms
更新二:
看起来@Gulzar 是对的。我将批量大小更改为 1000 (val=1000
) 并且 CPU 输出:
Wall time: 8min 44s
当 GPU 输出时:
Wall time: 3min 12s
挥手回答
GPU 是“较弱”的计算机,计算核心比 CPU 多得多。
数据必须以“昂贵”的方式从 RAM 内存传递给他们,每隔一段时间,这样他们就可以处理它。
如果数据“大”,并且可以对该数据进行并行处理,则计算速度可能会更快。
如果数据“不够大”,传输数据的成本,或使用较弱内核并同步它们的成本可能会超过并行化的好处。
GPU什么时候有用?
- 对于更大的网络,或更重的计算,例如卷积,或更大的全连接层(更大的矩阵乘法)
- 对于较大的批次 - 批次是并行计算的一种非常简单的方法,因为它们(几乎*)是独立的。 *几乎,因为它们确实需要在某些时候以编程方式同步。