正确使用PyTorch的non_blocking=True进行数据预取

hc8w905p  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(142)

我正在研究当模型在GPU上训练时从CPU预取数据到GPU中。将CPU到GPU的数据传输与GPU模型训练重叠,
1.使用data = data.cuda(non_blocking=True)将数据传输到GPU
1.使用train_loader = DataLoader(..., pin_memory=True)将数据固定到CPU内存
然而,我无法理解在这个官方PyTorch示例中如何执行非阻塞传输,特别是这个代码块:

for i, (images, target) in enumerate(train_loader):
        # measure data loading time
        data_time.update(time.time() - end)

        if args.gpu is not None:
            images = images.cuda(args.gpu, non_blocking=True)
        if torch.cuda.is_available():
            target = target.cuda(args.gpu, non_blocking=True)

        # compute output
        output = model(images)
        loss = criterion(output, target)

在执行output = model(images)之前,images.cuda(non_blocking=True)target.cuda(non_blocking=True)是否必须完成?由于这是一个同步点,images必须首先完全传输到CUDA设备,因此数据传输步骤实际上不再是非阻塞的。
由于output = model(images)是阻塞的,所以for循环的下一次i迭代中的images.cuda()target.cuda()将不会发生,直到计算出模型输出,这意味着下一次循环迭代中没有预取。
如果这是正确的,那么对GPU执行数据预取的正确方法是什么?

j9per5c4

j9per5c41#

我认为你错了,output = model(images)是一个同步点。似乎计算是由GPU的不同部分处理的。引用PyTorch官方文档:
此外,一旦固定了Tensor或存储,就可以使用异步GPU副本。只需将一个额外的non_blocking=True参数传递给to()cuda()调用。这可用于将数据传输与计算重叠

qlfbtfca

qlfbtfca2#

要在PyTorch上正确实现GPU预取,必须将for循环转换为while循环。
应该使用iter函数将DataLoader改为迭代器,例如:iterator = iter(loader)
在while-loop中的每一步使用next(iterator)来获取下一个minibatch。
DataLoader的结尾可以通过从迭代器中捕获StopIteration来检测。
StopIteration被引发时,使用一个标志来结束while-loop。

相关问题