Repository: facebookresearch/ParlAI

Issue:
Multiple CNN initializations causing memory leak
CNN initialized multiple number of times for multibatch
https://github.com/facebookresearch/ParlAI/blob/879bb1502a449a72d82603cc56c87c168fe78ace/parlai/core/image_featurizers.py#L101


Discussion:
`if not self.netCNN` should only evaluate to True the first time this function is called. let us know what you find!
You can reproduce the issue by checking if it goes inside that scope (adding a print statement). 
I got the same using `python examples/display_data.py -t vqa_v1:all -bs 8 --image-mode resnet152` which prints the check multiple times.

Resolving patch:
diff --git a/parlai/core/image_featurizers.py b/parlai/core/image_featurizers.py
--- a/parlai/core/image_featurizers.py
+++ b/parlai/core/image_featurizers.py
@@ -142,6 +142,7 @@ def load(self, path):
             if not os.path.exists(dpath):
                 build_data.make_dir(dpath)
 
+            imagefn = imagefn.split('.')[0]
             imagefn = imagefn + '.npy'
             new_path = os.path.join(prepath, mode, imagefn)
 
diff --git a/parlai/tasks/vqa_v1/agents.py b/parlai/tasks/vqa_v1/agents.py
--- a/parlai/tasks/vqa_v1/agents.py
+++ b/parlai/tasks/vqa_v1/agents.py
@@ -58,15 +58,16 @@ def __init__(self, opt, shared=None):
             self.ques = shared['ques']
             if 'annotation' in shared:
                 self.annotation = shared['annotation']
+            self.image_loader = shared['image_loader']
         else:
             self._setup_data(data_path, annotation_path)
+            self.image_loader = ImageLoader(opt)
 
         # for ordered data in batch mode (especially, for validation and
         # testing), each teacher in the batch gets a start index and a step
         # size so they all process disparate sets of the data
         self.step_size = opt.get('batchsize', 1)
         self.data_offset = opt.get('batchindex', 0)
-        self.image_loader = ImageLoader(opt)
         self.reset()
 
     def __len__(self):
@@ -120,6 +121,7 @@ def share(self):
         shared['ques'] = self.ques
         if hasattr(self, 'annotation'):
             shared['annotation'] = self.annotation
+        shared['image_loader'] = self.image_loader
         return shared
 
     def _setup_data(self, data_path, annotation_path):
diff --git a/parlai/tasks/vqa_v2/agents.py b/parlai/tasks/vqa_v2/agents.py
--- a/parlai/tasks/vqa_v2/agents.py
+++ b/parlai/tasks/vqa_v2/agents.py
@@ -58,8 +58,11 @@ def __init__(self, opt, shared=None):
             self.ques = shared['ques']
             if 'annotation' in shared:
                 self.annotation = shared['annotation']
+            self.image_loader = shared['image_loader']
         else:
             self._setup_data(data_path, annotation_path)
+            self.image_loader = ImageLoader(opt)
+
         self.len = len(self.ques['questions'])
 
         # for ordered data in batch mode (especially, for validation and
@@ -67,7 +70,6 @@ def __init__(self, opt, shared=None):
         # size so they all process disparate sets of the data
         self.step_size = opt.get('batchsize', 1)
         self.data_offset = opt.get('batchindex', 0)
-        self.image_loader = ImageLoader(opt)
 
         self.reset()
 
@@ -122,6 +124,7 @@ def share(self):
         shared['ques'] = self.ques
         if hasattr(self, 'annotation'):
             shared['annotation'] = self.annotation
+        shared['image_loader'] = self.image_loader
         return shared
 
     def _setup_data(self, data_path, annotation_path):


Test patch: