[DataLoader] num_of_worker>0 error

Moonlight: <p>i use window 10 pro, graphic card geforce 1050ti, and anaconda spyder python3.7</p>
<p>I am learning about Unet and practice code.</p>
<p>but i have some problem. Maybe… enumerate{dataLoader]) make error.</p>
<p>==============<br>
i use this code for dataset and dataloader</p>
<p>class Dataset(object):<br>
def <strong>init</strong>(self, fname ,img_transform=None, mask_transform = None, edge_weight= False):<br>
<span class="hashtag">#nothing</span> special here, just internalizing the constructor parameters<br>
self.fname=fname<br>
self.edge_weight = edge_weight</p>
<pre><code>    self.img_transform=img_transform
    self.mask_transform = mask_transform
    
    self.tables=tables.open_file(self.fname)
    self.numpixels=self.tables.root.numpixels[:]
    self.nitems=self.tables.root.img.shape[0]
    self.tables.close()
    
    self.img = None
    self.mask = None
    
def __getitem__(self, index):
    #opening should be done in __init__ but seems to be
    #an issue with multithreading so doing here
    with tables.open_file(self.fname,'r') as db:
        self.img=db.root.img
        self.mask=db.root.mask
   
        #get the requested image and mask from the pytable
        img = self.img[index,:,:,:]
        mask = self.mask[index,:,:]
    
    #the original Unet paper assignes increased weights to the edges of the annotated objects
    #their method is more sophistocated, but this one is faster, we simply dilate the mask and 
    #highlight all the pixels which were "added"
    if(self.edge_weight):
        weight = scipy.ndimage.morphology.binary_dilation(mask==1, iterations =2) &amp; ~mask
    else: #otherwise the edge weight is all ones and thus has no affect
        weight = np.ones(mask.shape,dtype=mask.dtype)
    
    mask = mask[:,:,None].repeat(3,axis=2) #in order to use the transformations given by torchvision
    weight = weight[:,:,None].repeat(3,axis=2) #inputs need to be 3D, so here we convert from 1d to 3d by repetition
    
    img_new = img
    mask_new = mask
    weight_new = weight
    
    seed = random.randrange(sys.maxsize) #get a random seed so that we can reproducibly do the transofrmations
    if self.img_transform is not None:
        random.seed(seed) # apply this seed to img transforms
        img_new = self.img_transform(img)

    if self.mask_transform is not None:
        random.seed(seed)
        mask_new = self.mask_transform(mask)
        mask_new = np.asarray(mask_new)[:,:,0].squeeze()
        
        random.seed(seed)
        weight_new = self.mask_transform(weight)
        weight_new = np.asarray(weight_new)[:,:,0].squeeze()

    return img_new, mask_new, weight_new
def __len__(self):
    return self.nitems
</code></pre>
<h1>In[ ]:</h1>
<p><span class="hashtag">#note</span> that since we need the transofrmations to be reproducible for both masks and images<br>
<span class="hashtag">#we</span> do the spatial transformations first, and afterwards do any color augmentations<br>
img_transform = transforms.Compose([<br>
transforms.ToPILImage(),<br>
transforms.RandomVerticalFlip(),<br>
transforms.RandomHorizontalFlip(),<br>
transforms.RandomCrop(size=(patch_size,patch_size),pad_if_needed=True), <span class="hashtag">#these</span> need to be in a reproducible order, first affine transforms and then color<br>
transforms.RandomResizedCrop(size=patch_size),<br>
transforms.RandomRotation(180),<br>
transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=.5),<br>
transforms.RandomGrayscale(),<br>
transforms.ToTensor()<br>
])</p>
<p>mask_transform = transforms.Compose([<br>
transforms.ToPILImage(),<br>
transforms.RandomVerticalFlip(),<br>
transforms.RandomHorizontalFlip(),<br>
transforms.RandomCrop(size=(patch_size,patch_size),pad_if_needed=True), <span class="hashtag">#these</span> need to be in a reproducible order, first affine transforms and then color<br>
transforms.RandomResizedCrop(size=patch_size,interpolation=PIL.Image.NEAREST),<br>
transforms.RandomRotation(180),<br>
])</p>
<p>dataset={}<br>
dataLoader={}<br>
for phase in phases: <span class="hashtag">#now</span> for each of the phases, we’re creating the dataloader<br>
<span class="hashtag">#interestingly</span>, given the batch size, i’ve not seen any improvements from using a num_workers&gt;0</p>
<pre><code>dataset[phase]=Dataset(f"./{dataname}_{phase}.pytable", img_transform=img_transform , mask_transform = mask_transform ,edge_weight=edge_weight)
dataLoader[phase]=DataLoader(dataset[phase], batch_size=batch_size, shuffle=True, num_workers=2, pin_memory=True)
</code></pre>
<p>=======================================</p>
<p>Then, using this code, some error occurs.</p>
<p>writer=SummaryWriter() <span class="hashtag">#open</span> the tensorboard visualiser<br>
best_loss_on_test = np.Infinity<br>
edge_weight=torch.tensor(edge_weight).to(device)<br>
start_time = time.time()<br>
for epoch in range(num_epochs):<br>
<span class="hashtag">#zero</span> out epoch based performance variables<br>
all_acc = {key: 0 for key in phases}<br>
all_loss = {key: torch.zeros(0).to(device) for key in phases}<br>
cmatrix = {key: np.zeros((2,2)) for key in phases}</p>
<pre><code>for phase in phases: #iterate through both training and validation states

    if phase == 'train':
        model.train()  # Set model to training mode
    else: #when in eval mode, we don't want parameters to be updated
        model.eval()   # Set model to evaluate mode

    for ii , [X, y, y_weight] in enumerate(dataLoader[phase]): #for each of the batches
        X = X.to(device)  # [Nbatch, 3, H, W]
        y_weight = y_weight.type('torch.FloatTensor').to(device)
        y = y.type('torch.LongTensor').to(device)  # [Nbatch, H, W] with class indices (0, 1)

        with torch.set_grad_enabled(phase == 'train'): #dynamically set gradient computation, in case of validation, this isn't needed
                                                        #disabling is good practice and improves inference time

            prediction = model(X)  # [N, Nclass, H, W]
            loss_matrix = criterion(prediction, y)
            loss = (loss_matrix * (edge_weight**y_weight)).mean() #can skip if edge weight==1

            if phase=="train": #in case we're in train mode, need to do back propogation
                optim.zero_grad()
                loss.backward()
                optim.step()
                train_loss = loss


            all_loss[phase]=torch.cat((all_loss[phase],loss.detach().view(1,-1)))

            if phase in validation_phases: #if this phase is part of validation, compute confusion matrix
                p=prediction[:,:,:,:].detach().cpu().numpy()
                cpredflat=np.argmax(p,axis=1).flatten()
                yflat=y.cpu().numpy().flatten()

                cmatrix[phase]=cmatrix[phase]+confusion_matrix(yflat,cpredflat,labels=range(n_classes))

    all_acc[phase]=(cmatrix[phase]/cmatrix[phase].sum()).trace()
    all_loss[phase] = all_loss[phase].cpu().numpy().mean()

    #save metrics to tensorboard
    writer.add_scalar(f'{phase}/loss', all_loss[phase], epoch)
    if phase in validation_phases:
        writer.add_scalar(f'{phase}/acc', all_acc[phase], epoch)
        writer.add_scalar(f'{phase}/TN', cmatrix[phase][0,0], epoch)
        writer.add_scalar(f'{phase}/TP', cmatrix[phase][1,1], epoch)
        writer.add_scalar(f'{phase}/FP', cmatrix[phase][0,1], epoch)
        writer.add_scalar(f'{phase}/FN', cmatrix[phase][1,0], epoch)
        writer.add_scalar(f'{phase}/TNR', cmatrix[phase][0,0]/(cmatrix[phase][0,0]+cmatrix[phase][0,1]), epoch)
        writer.add_scalar(f'{phase}/TPR', cmatrix[phase][1,1]/(cmatrix[phase][1,1]+cmatrix[phase][1,0]), epoch)

print('%s ([%d/%d] %d%%), train loss: %.4f test loss: %.4f' % (timeSince(start_time, (epoch+1) / num_epochs), epoch+1, num_epochs ,(epoch+1) / num_epochs * 100, all_loss["train"], all_loss["val"]),end="")    

#if current loss is the best we've seen, save model state with all variables
#necessary for recreation
if all_loss["val"] &lt; best_loss_on_test:
    best_loss_on_test = all_loss["val"]
    print("  **")
    state = {'epoch': epoch + 1,
     'model_dict': model.state_dict(),
     'optim_dict': optim.state_dict(),
     'best_loss_on_test': all_loss,
     'n_classes': n_classes,
     'in_channels': in_channels,
     'padding': padding,
     'depth': depth,
     'wf': wf,
     'up_mode': up_mode, 'batch_norm': batch_norm}


    torch.save(state, f"{dataname}_unet_best_model.pth")
else:
    print("")
</code></pre>
<p>error is…</p>
<p>ipdb&gt; Traceback (most recent call last):</p>
<p>File “”, line 1, in <br>
debugfile(‘C:/Users/mbmhm/Desktop/unet/train_unet.py’, wdir=‘C:/Users/mbmhm/Desktop/unet’)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 856, in debugfile<br>
debugger.run(“runfile(%r, args=%r, wdir=%r)” % (filename, args, wdir))</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\bdb.py”, line 585, in run<br>
exec(cmd, globals, locals)</p>
<p>File “”, line 1, in </p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 827, in runfile<br>
execfile(filename, namespace)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 110, in execfile<br>
exec(compile(f.read(), filename, ‘exec’), namespace)</p>
<p>File “c:/users/mbmhm/desktop/unet/train_unet.py”, line 265, in <br>
for ii , [X, y, y_weight] in enumerate(dataLoader[phase]): <span class="hashtag">#for</span> each of the batches</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\torch\utils\data\dataloader.py”, line 193, in <strong>iter</strong><br>
return _DataLoaderIter(self)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\torch\utils\data\dataloader.py”, line 469, in <strong>init</strong><br>
w.start()</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\multiprocessing\process.py”, line 112, in start<br>
self._popen = self._Popen(self)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\multiprocessing\context.py”, line 223, in _Popen<br>
return _default_context.get_context().Process._Popen(process_obj)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\multiprocessing\context.py”, line 322, in _Popen<br>
return Popen(process_obj)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\multiprocessing\popen_spawn_win32.py”, line 89, in <strong>init</strong><br>
reduction.dump(process_obj, to_child)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\multiprocessing\reduction.py”, line 60, in dump<br>
ForkingPickler(file, protocol).dump(obj)</p>
<p>File “stringsource”, line 2, in tables.hdf5extension.Array.<strong>reduce_cython</strong></p>
<p>TypeError: self.dims,self.dims_chunk,self.maxdims cannot be converted to a Python object for pickling</p>
<p>===================================<br>
I use different code, but error occer.</p>
<p>for x,y,w in dataLoader[‘train’]:<br>
print(x.shape, y.shape, w.shape)</p>
<p>ipdb&gt; _CudaDeviceProperties(name=‘GeForce GTX 1050 Ti’, major=6, minor=1, total_memory=4096MB, multi_processor_count=6)<br>
total params:   122466</p>
<p>ipdb&gt; Traceback (most recent call last):</p>
<p>File “”, line 1, in <br>
debugfile(‘C:/Users/mbmhm/Desktop/unet/train_unet.py’, wdir=‘C:/Users/mbmhm/Desktop/unet’)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 856, in debugfile<br>
debugger.run(“runfile(%r, args=%r, wdir=%r)” % (filename, args, wdir))</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\bdb.py”, line 585, in run<br>
exec(cmd, globals, locals)</p>
<p>File “”, line 1, in </p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 827, in runfile<br>
execfile(filename, namespace)</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\spyder_kernels\customize\spydercustomize.py”, line 110, in execfile<br>
exec(compile(f.read(), filename, ‘exec’), namespace)</p>
<p>File “c:/users/mbmhm/desktop/unet/train_unet.py”, line 200, in <br>
for x,y,w in dataLoader[‘train’]:</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\torch\utils\data\dataloader.py”, line 576, in <strong>next</strong><br>
idx, batch = self._get_batch()</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\torch\utils\data\dataloader.py”, line 543, in _get_batch<br>
success, data = self._try_get_batch()</p>
<p>File “C:\Users\mbmhm\ansel\Anaconda3\envs\moongpu\lib\site-packages\torch\utils\data\dataloader.py”, line 519, in _try_get_batch<br>
raise RuntimeError(‘DataLoader worker (pid(s) {}) exited unexpectedly’.format(pids_str))</p>
<p>RuntimeError: DataLoader worker (pid(s) 500, 6872) exited unexpectedly</p>
<p>what can i do to solve this problem.</p>

ptrblck: <p>Could you run your code with <code>num_workers=0</code> and check, if you get a proper error message?<br>
Maybe something raises an error in your <code>__getitem__</code>, which might be lost due to multiprocessing.</p>