Batch size of batches returned by data loader sometimes different when using IterableDataset and multiple workers

visionscaper: <p>Hi,</p>
<p>I have this issue with DataLoaders I have never seen before. It only occurs when using an IterableDataset and multiple DataLoader workers. What I have observed is that when the batch size should be (e.g.) 72, sometimes the batches produced by the DataLoaders have other smaller sizes, e.g. I get the batch sizes over time as follows (scenario is DistributedDataParallel training with multiple workers per DataLoader):</p>
<p>Device 0: 72 72 72 72 … <strong>20</strong> 72 … <strong>4</strong> 72 72 …<br>
Device 1: 72 72 27 72 … 72 72 <strong>18</strong> 72 72 …</p>
<p>Etc.</p>
<p>So this is not about a trailing batch with a smaller size, but seemingly randomly, sometimes the batches produced by the DataLoaders are smaller than expected!</p>
<p>My question is, is this know behaviour of DataLoaders that use IterableDatasets and multiple workers?<br>
How could something like this be caused by my IterableDataset implementation?<br>
Could this be a bug in the DataLoader code?</p>
<p>I’m tearing my hear out over this one …</p>

tom: <p>Did you try to use <code>drop_last = True</code>? Do you know if this happnes when the IterableDataset indicates that it does not have more data?<br>
The second note on the <a href="https://pytorch.org/docs/stable/data.html#automatic-batching-default" rel="noopener nofollow ugc">DataLoader documentation on batching</a> seems to imply that that might help.</p>
<p>Best regards</p>
<p>Thomas</p>

visionscaper: <p>Thanks <a class="mention" href="/u/tom">@tom</a>, as I have stated, this does not happen at the last batch, so drop_last=True would probably not help. Further, I do log when the IterableDataset has no more samples, but this is not the case; if it were, the DataLoader would also not be able to create a next batch that has the full batch size.</p>
<p>Please see the batch size pattern over time that I shared; the batch size sometimes drops to a lower number … but continues with the normal batch size afterwards. It’s really odd, this should not happen with DataLoaders, right?</p>

visionscaper: <p>Hi <a class="mention" href="/u/tom">@tom</a>, I investigated this further and found that setting <code>drop_last=True</code> worked for me. Initially I didn’t expect this to work because I had a different mental model about how the Dataloader uses the workers to create batches. I was under the impression that the workers would provide individual samples, and that subsequently the dataloader would package these samples in to batches. In this model only the very last batch can be incomplete.</p>
<p>However, apparently, the workers provide complete batches, and thus when the IterableDataset of the worker reaches its end, the trailing batch can have less samples.</p>
<p>These incomplete batches can appear anywhere in the stream of batches because if the dataset for one worker is depleted the other workers simply continue to produce batches.</p>
<p>Is this is a correct description of what happens?</p>

tom: <p>This is approximately what I had in mind, yes. In particular that workers provide batches.<br>
To my mind, this not aspect of <code>IterableDataset</code>'s  behaviour, which is more a result of the technical constraints than the ideal “intuitive” behaviour, is much of the attraction of classic map-style datasets which seem to be closer to what people expect.</p>
<p>Best regards</p>
<p>Thomas</p>
<p>P.S.: Glad it’s solved. <img src="https://discuss.pytorch.org/images/emoji/apple/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>