平时的代码:
train_loader = torch.utils.data.DataLoader(
Vlog.VlogSet(params, is_train=True,frame_gap=args.frame_gap),
batch_size=params['batchSize'],
shuffle=True,
num_workers=args.workers,
pin_memory=True)
for batch_idx, (imgs, img, patch2, theta, meta) in enumerate(train_loader):
#训练代码
改过的代码:
class data_prefetcher():
def __init__(self, loader):
self.loader = iter(loader)
self.stream = torch.cuda.Stream()
self.preload()
def preload(self):
try:
self.imgs, self.img, self.patch2, self.theta, self.meta = next(self.loader)
except StopIteration:
self.next_input = None
return
with torch.cuda.stream(self.stream):
self.imgs = self.imgs.cuda(non_blocking=True)
self.img = self.img.cuda(non_blocking=True)
self.patch2 = self.patch2.cuda(non_blocking=True)
self.theta = self.theta.cuda(non_blocking=True)
def next(self):
torch.cuda.current_stream().wait_stream(self.stream)
imgs = self.imgs
img = self.img
patch2 = self.patch2
theta = self.theta
meta = self.meta
self.preload()
return imgs, img, patch2, theta, meta
prefetcher = data_prefetcher(train_loader)
(imgs, img, patch2, theta, meta) = prefetcher.next()
batch_idx = 0
while data is not None:
batch_idx += 1
#训练代码
(imgs, img, patch2, theta, meta) = prefetcher.next()
大功告成,gpu利用率蹭蹭上来,当然最好还是把机械硬盘换成ssd
参考:这个情况nVidia给出了解决方案
https://github.com/NVIDIA/apex/blob/f5cd5ae937f168c763985f627bbf850648ea5f3f/examples/imagenet/main_amp.py#L256
在调整num_workers的过程中,发现训练速度并没有变化,原因在于:
num_workers是加载数据(batch)的线程数目
当加载batch的时间 < 数据训练的时间
GPU每次训练完都可以直接从CPU中取到next batch的数据
无需额外的等待,因此也不需要多余的worker,即使增加worker也不会影响训练速度
当加载batch的时间 > 数据训练的时间
GPU每次训练完都需要等待CPU完成数据的载入
若增加worker,即使worker_1还未就绪,GPU也可以取worker_2的数据来训练
仅限单线程训练情况
写在结尾:对于dataloader特别大的情况好像并无luan用,开了100个线程喂进去100个batch,接下来又是漫长的等待。
DataLoader num_workers与torch.set_num_threads的区别:
num_workers设置DataLoader在实现数据预处理的并行化的进程数,并没有设置线程。
set_num_threads()设置Pytorch进行CPU多线程并行计算时所占用的线程数。