簡體   English   中英

為什么我的DataLoader比for循環慢得多?

[英]Why is my DataLoader so much slower than a for loop?

我正在為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是錯誤的,還是這只是錯誤的用例,循環更適合我正在做的事情?

編輯:這里有兩個小提琴,包含循環的完整代碼和dataloader變體

編輯:我相信我可能已經想出如何解決我的主要問題,dataloader和循環之間的性能差異。 通過將加載器的num_workers參數設置為8,我設法將GPU上的DL小批量的時間減少到大約1分鍾。 雖然這肯定好於5分鍾,但它仍然很糟糕,考慮到在GPU上使用DL的miniatch與具有CPU循環的minibatch的性能相當。

transforms.ToTensor()需要PIL Imagenp.ndarray在范圍[0, 255]作為輸入,並把它轉換成一個torch.FloatTensor范圍[0.0, 1.0]如果np.ndarray具有dtype=np.uint8PIL Image屬於其中一種模式(L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1) docs

重新縮放和更改數據類型會影響模型的准確性。 此外, DataLoader比批量循環更多的操作,因此時間上的差異。

PS在進行小型訓練培訓時,您應該隨機播放訓練數據

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM