Итак, я пытаюсь использовать DataLoader
в pytorch для обучения нейронной сети.В каждой партии я хотел бы получить изображения, маски и имена файлов.Чтобы сопоставить имена файлов, я написал собственную функцию сортировки.
По некоторым причинам мой код вылетает всякий раз, когда я устанавливаю num_workers > 0
в DataLoader
, но отлично работает, когда num_workers = 0
.Я получаю сообщение об ошибке, подобное приведенному ниже, которое не очень полезно:
RuntimeError: работник DataLoader (pid 10449) прерывается сигналом: прекращено.Детали теряются из-за многопроцессорности.Повторный запуск с num_workers = 0 может дать лучшую трассировку ошибок.
Кто-нибудь знает, что не так и как я могу отлаживать многопроцессорные процессы в pytorch?
class MyDataset(Dataset):
def __init__(self, df=None):
self.folderlist = []
# Load path of files here... df is just a dataframe of which specifies which files to load.
def __len__(self):
return len(self.folderlist)
def __getitem__(self, idx):
imglist = os.listdir( self.folderlist[idx])
image_name = [x for x in imglist if x.endswith(('_img.jpg'))][0]
mask_name = [x for x in imglist if x.endswith(('_mask.png'))][0]
image = np.array(Image.open(os.path.join(self.folderlist[idx], image_name)))
mask = Image.open(os.path.join(self.folderlist[idx], mask_name))
# Some transforms here
image = transforms.ToTensor()(image)
mask = transforms.ToTensor()(mask)
return (image, mask, self.folderlist[idx]) # returns the filename as well
def collate_fn(batch, default=False, depth=0):
if default:
return default_collate(batch)
else:
if isinstance(batch[0], torch.Tensor):
if True:
# If we're in a background process, concatenate directly into a
# shared memory tensor to avoid an extra copy
numel = sum([x.numel() for x in batch])
storage = batch[0].storage()._new_shared(numel)
out = batch[0].new(storage)
return torch.stack(batch, 0, out=out)
elif isinstance(batch[0], int_classes):
return torch.LongTensor(batch)
elif isinstance(batch[0], float):
return torch.DoubleTensor(batch)
elif isinstance(batch[0], string_classes):
return batch
elif (depth==0):
# Puts the first two data fields into a tensor with outer dimension batch size
transposed = zip(*batch)
return [collate_fn(samples, depth=depth+1) for samples in transposed]
else:
return batch # Don't zip up second+ order lists
# Some class function
def train():
# ...
train_dataset = MyDataset(df=df_train)
train_loader = DataLoader(train_dataset, batch_size=self.config.TRAIN_BS, shuffle=True, num_workers=self.config.NUM_WORKERS, collate_fn=collate_fn)
val_dataset = MyDataset(df=df_val)
val_loader = DataLoader(val_dataset, batch_size=self.config.VAL_BS, shuffle=True, num_workers=self.config.NUM_WORKERS, collate_fn=collate_fn)
nfiles = 0
for i, (images, masks, filenames) in enumerate(train_loader):
nfiles += len(filenames)
print('train {}; nfiles: {}'.format(filenames, nfiles))
for i, (images, masks, filenames) in enumerate(val_loader):
print('val {}; nfiles: {}'.format(filenames, nfiles))
Сбои программы после завершения итерации через train_loader.