python - 几次迭代后,Pytorch 速度变慢
问题描述
我正在尝试在 PyTorch 中实现一个模型。训练过程相当复杂,需要一些时间,但我注意到模型在前几批非常快,然后突然达到 500 左右。我猜是由于一些内存泄漏问题,好像 python并没有真正释放释放的巨大张量的内存。
起初我以为问题与存储梯度有关,但实际上即使torch.no_grad()
出现了同样的问题。
这是一个复制问题的示例。(注意我不是在尝试训练这个特定的网络,但问题看起来是一样的)。为了使事情更简单,我没有使用渐变,而是在同一批次上进行迭代。
import torch
import torch.nn as nn
from torchvision.datasets import MNIST
import torchvision.transforms as T
dataset = MNIST(root='./MNIST', train=True, download=True,
transform=T.Compose([T.ToTensor(), T.Lambda(lambda x: torch.flatten(x))]))
data_loader = torch.utils.data.DataLoader(dataset, batch_size=500)
X, _ = next(iter(data_loader))
X = X.to('cuda')
in_features = 28*28
out_features = 10
width= 15000
#defining huge network
NN = nn.Sequential(
nn.Linear(in_features=28*28, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=width, bias=False),
nn.ReLU(),
nn.Linear(in_features=width, out_features=out_features, bias=False),
).to('cuda')
import time
iterations=100
X = X.to('cuda')
with torch.no_grad():
for idx in range(iterations):
print(f'Iteration {idx+1}')
start = time.time()
Y = NN(X)
print(f'Time: {time.time() - start}')
输出显示一切都非常快,直到第 50 次迭代,然后它突然变慢了。
Iteration 44
Time: 0.00035953521728515625
Iteration 45
Time: 0.00035309791564941406
Iteration 46
Time: 0.00035309791564941406
Iteration 47
Time: 0.048192501068115234
Iteration 48
Time: 0.1714644432067871
Iteration 49
Time: 0.16771984100341797
Iteration 50
Time: 0.1681973934173584
Iteration 51
Time: 0.16853046417236328
Iteration 52
Time: 0.16821908950805664
为什么会出现这样的减速?有没有可能以某种方式避免它?
解决方案
查看此页面并向下滚动到“异步执行”。
基本上,您测量的是将操作排入 GPU 的时间,而不是实际执行操作所需的时间。这是因为 GPU 调用是异步的,如链接中所述。我复制了下面的相关部分:
默认情况下,GPU 操作是异步的。当您调用使用 GPU 的函数时,这些操作将被排入特定设备的队列,但不一定要等到稍后才会执行。这使我们能够并行执行更多计算,包括在 CPU 或其他 GPU 上的操作。
一般来说,异步计算的效果对调用者来说是不可见的,因为(1)每个设备按照它们排队的顺序执行操作,(2)PyTorch 在 CPU 和 GPU 之间或两个 GPU 之间复制数据时会自动执行必要的同步。因此,计算将像每个操作都同步执行一样进行。
您可以通过设置环境变量 CUDA_LAUNCH_BLOCKING=1 来强制同步计算。当 GPU 发生错误时,这会很方便。(对于异步执行,直到操作实际执行后才会报告此类错误,因此堆栈跟踪不会显示请求的位置。)
异步计算的结果是没有同步的时间测量是不准确的。要获得精确的测量值,应该在测量之前调用 torch.cuda.synchronize(),或者使用torch.cuda.Event
如下方式记录时间:
start_event = torch.cuda.Event(enable_timing=True)
end_event = torch.cuda.Event(enable_timing=True)
start_event.record()
# Run some things here
end_event.record()
torch.cuda.synchronize() # Wait for the events to be recorded!
elapsed_time_ms = start_event.elapsed_time(end_event)
推荐阅读
- javascript - Amcharts Candle-Stick 气球文本以错误的格式显示时间戳
- c# - C# AspNetCore SignalR 客户端 - 连接关闭处理程序
- visual-studio - Visual Studio 2019 - 浏览器链接不起作用
- node.js - 填充 mongoose.Schema.Types.ObjectId 数组
- django - Django-Rest-Framework CreateAPIView 不起作用
- android - 无法构建 React Native 0.59.8 android.support.v4.net.ConnectivityManagerCompat
- c++ - 仅将纪元字符串保存到mysql datetime 年/月/日,但没有小时分秒
- r - Shinyproxy - 如何将主机传递给 docker 映像
- c# - 序列号和精度问题
- android - 如何使用列表视图改进应用程序的设置选项界面?