首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么我的DataLoader比for循环慢这么多?

为什么我的DataLoader比for循环慢这么多?
EN

Stack Overflow用户
提问于 2019-05-13 00:14:16
回答 1查看 1.3K关注 0票数 1

我正在为MNIST数据集编写一个基于神经网络的分类器。我首先尝试使用周期和批处理的循环和索引手动加载数据。在一篇教程中,我看到有人使用torch.utils.data.DataLoader来完成这项任务,所以我更改了代码,改为使用DataLoader。这导致了学习过程中持续时间的重大差异。

我试图通过使用基准来缩小范围来解决这个问题。我总是在中央处理器(I7 8700k)和图形处理器(1080ti)上进行基准测试,数据存储在我的固态硬盘(970evo)上。

我首先尝试比较使用和不使用DataLoader的批量梯度下降,然后比较使用和不使用DataLoader的小批量梯度下降。结果让我很困惑。

代码语言:javascript
运行
复制
|                 | 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的代码,精简为要点。

代码语言:javascript
运行
复制
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使用循环的代码

代码语言:javascript
运行
复制
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,或者这只是一个错误的用例,循环更适合我正在做的事情?

编辑:这里有两个小提琴,包含loopdataloader变体的完整代码

编辑:我相信我可能已经解决了我的主要问题,dataloader和循环之间的性能差异。通过将加载器的num_workers参数设置为8,我设法将在图形处理器上使用DL的小批量处理时间降低到1分钟左右。虽然这肯定比5分钟要好,但考虑到在GPU上使用DL的minibatch与在CPU上使用循环的minibatch的性能相当,这仍然很糟糕。

EN

回答 1

Stack Overflow用户

发布于 2019-05-16 17:22:57

transforms.ToTensor()[0, 255]范围内的 PIL Imagenp.ndarray 作为输入,并将其转换为 [0.0, 1.0] 范围内的 torch.FloatTensor如果 np.ndarray具有 dtype=np.uint8PIL Image属于模式之一(L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)docs

重新缩放和更改数据类型会影响模型精度。此外,DataLoader在批处理上执行的操作比您的循环更多,因此计时上的差异。

附注:在进行小批量训练时,您应该对训练数据进行混洗

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56101111

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档