我正在研究当模型在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执行数据预取的正确方法是什么?
2条答案
按热度按时间j9per5c41#
我认为你错了,
output = model(images)
是一个同步点。似乎计算是由GPU的不同部分处理的。引用PyTorch官方文档:此外,一旦固定了Tensor或存储,就可以使用异步GPU副本。只需将一个额外的
non_blocking=True
参数传递给to()
或cuda()
调用。这可用于将数据传输与计算重叠。qlfbtfca2#
要在PyTorch上正确实现GPU预取,必须将for循环转换为while循环。
应该使用
iter
函数将DataLoader改为迭代器,例如:iterator = iter(loader)
。在while-loop中的每一步使用
next(iterator)
来获取下一个minibatch。DataLoader的结尾可以通过从迭代器中捕获
StopIteration
来检测。当
StopIteration
被引发时,使用一个标志来结束while-loop。