python - 为什么我的 DataLoader 比 for 循环慢得多?
问题描述
我正在为 MNIST 数据集编写一个基于神经网络的分类器。我首先尝试使用周期和批次的循环和索引手动加载数据。在一个教程中,我看到有人使用 torch.utils.data.DataLoader 来完成这个确切的任务,所以我将代码更改为使用 DataLoader。这导致学习过程的持续时间存在重大差异。
我试图通过使用基准测试缩小范围来解决此问题。我总是在 CPU(i7 8700k) 和 GPU(1080ti) 上进行基准测试,数据存储在我的 ssd(970 evo) 上。
我首先尝试比较使用和不使用 DataLoader 的 Batch Gradient Descent,然后比较使用和不使用 DataLoader 的 Mini-Batch Gradient Descent。结果让我很困惑。
| | BGD | BGD with DL | MB-GD | MB-GD with DL |
|-----------------|-------------|-------------|-------------|---------------|
| Time on CPU | 00:00:56.70 | 00:05:59.31 | 00:01:31.29 | 00:07:46.56 |
| Accuracy on CPU | 82.47 | 33.44 | 94.84 | 87.67 |
| Time on GPU | 00:00:15.89 | 00:05:41.79 | 00:00:17.48 | 00:05:37.33 |
| Accuracy on GPU | 82.3 | 30.66 | 94.88 | 87.74 |
| Batch Size | M | M | 500 | 500 |
| Epoch | 100 | 100 | 100 | 100 |
这是使用 DataLoader 的代码,精简为基本要素。
num_epoch = 100
train_loader = DataLoader(batch_size=500, shuffle=False, dataset=dataset_train)
for epoch in range(num_epoch):
for i, (images, labels) in enumerate(train_loader):
images = images.view(-1, 28 * 28)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
vs 使用循环的代码
num_epoch = 100
batch_size = 500
num_batch = int(len(dataset_train) / batch_size)
for epoch in range(num_epoch):
for batch_idx in range(num_batch):
images = dataset_train.data[batch_idx*batch_size:(batch_idx+1)*batch_size].view(-1, 28 * 28)
labels = dataset_train.targets[batch_idx*batch_size:(batch_idx+1)*batch_size]
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
我希望 DataLoader 在时间和性能方面至少在接近循环的某个地方执行,但不会慢 10 倍。我也很困惑为什么 DataLoader 会影响模型的准确性。
我是否使用了错误的 DataLoader,或者这只是它的错误用例,而循环更适合我正在做的事情?
编辑:我相信我可能已经弄清楚如何解决我的主要问题,即数据加载器和循环之间的性能差异。通过将num_workers
加载程序的参数设置为 8,我设法将使用 GPU 上的 DL 进行 mini-batch 的时间缩短到 1 分钟左右。虽然这绝对比 5 分钟要好,但它仍然很糟糕,考虑到 GPU 上带有 DL 的 minibatch 与 CPU 上带有循环的 minibatch 的性能相当。
解决方案
transforms.ToTensor()
将范围内的PIL Image
或 作为输入,如果具有或属于其中一种模式文档,则将其转换为范围内的 anp.ndarray
[0, 255]
torch.FloatTensor
[0.0, 1.0]
np.ndarray
dtype=np.uint8
PIL Image
(L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)
重新缩放和更改数据类型会影响模型的准确性。也DataLoader
比你的批次循环做更多的操作,因此时间上的差异。
PS你应该在做小批量训练时打乱你的训练数据
推荐阅读
- javascript - Highcharts 限制将在 yAxis 上的类别中显示的项目数量
- azure - POST JSON 以将事件记录到 Application Insights
- postgresql - 如何从postgresql中表的更改列的结果中查询
- c++ - 如何避免此 C++ 代码中的算术异常?
- php - laravel中的redis问题
- php - PHP 变量始终为空
- javascript - React AXIOS post - 简单测试不起作用(快递)
- android - Android 应用内计费错误代码 - 错误 OR-IEH-02
- xamarin.android - “Resource.Designer.cs”在整个解决方案中更改后保留旧命名空间
- aframe - 如何以编程方式在 A-FRAME 场景中旋转相机?