def evaluate_default(self, img_ids=None):
        """
        Args:
            img_ids: a list of image IDs to evaluate on. Default to None for the whole dataset
        """

        if self._distributed:
            comm.synchronize()
            def gather(x, move=False):
                x = comm.gather(x)
                x = list(itertools.chain(*x))
                if move:
                    x = [xx.to(self._text_embeds[0].device) for xx in x]
                return x
            text_embeds = gather(self._text_embeds, move=True)
            image_embeds = gather(self._image_embeds, move=True)
            if self._ensemble:
                image_embeds2 = gather(self._image_embeds2, move=True)
            text_ids = gather(self._text_ids)
            image_ids = gather(self._image_ids)
            if not comm.is_main_process():
                return {}
        else:
            text_embeds = self._text_embeds
            image_embeds = self._image_embeds
            if self._ensemble:
                image_embeds2 = self._image_embeds2
            text_ids = self._text_ids
            image_ids = self._image_ids
        if len(text_embeds) == 0:
            self._logger.warning("[COCOCaptionEvaluator] Did not receive valid predictions.")
            return {}
        iids = torch.tensor(image_ids).view(-1).cuda()
        tiids = torch.tensor(text_ids).view(-1).cuda()
        image_embeds = torch.cat(image_embeds)
        text_embeds = torch.cat(text_embeds)
        image_embeds = image_embeds / image_embeds.norm(dim=-1, keepdim=True) 
        text_embeds = text_embeds / text_embeds.norm(dim=-1, keepdim=True) 
        scores = image_embeds @ text_embeds.t()

        if self._ensemble:
            image_embeds2 = torch.cat(image_embeds2)
            image_embeds2 = image_embeds2 / image_embeds2.norm(dim=-1, keepdim=True) 
            scores2 = image_embeds2 @ text_embeds.t()
            scores = scores2 * 0.5 + scores * 0.5

        topk10 = scores.topk(10, dim=1)
        topk5 = scores.topk(5, dim=1)
        topk1 = scores.topk(1, dim=1)
        topk10_iids = tiids[topk10.indices]
        topk5_iids = tiids[topk5.indices]
        topk1_iids = tiids[topk1.indices]
        tr_r10 = (iids.unsqueeze(1) == topk10_iids).float().max(dim=1)[0].mean()
        tr_r5 = (iids.unsqueeze(1) == topk5_iids).float().max(dim=1)[0].mean()
        tr_r1 = (iids.unsqueeze(1) == topk1_iids).float().max(dim=1)[0].mean()
        topk10 = scores.topk(10, dim=0)
        topk5 = scores.topk(5, dim=0)
        topk1 = scores.topk(1, dim=0)
        topk10_iids = iids[topk10.indices]
        topk5_iids = iids[topk5.indices]
        topk1_iids = iids[topk1.indices]
        ir_r10 = (tiids.unsqueeze(0) == topk10_iids).float().max(dim=0)[0].mean()
        ir_r5 = (tiids.unsqueeze(0) == topk5_iids).float().max(dim=0)[0].mean()
        ir_r1 = (tiids.unsqueeze(0) == topk1_iids).float().max(dim=0)[0].mean()
        self._results = OrderedDict()
        # Copy so the caller can do whatever with results
        self._results['recall'] = {}
        self._results['recall']['irtr'] = float("{:.3f}".format((ir_r1 + tr_r1).item() * 100))
        self._results['recall']['ir1'] = float("{:.3f}".format(ir_r1.item() * 100))
        self._results['recall']['ir5'] = float("{:.3f}".format(ir_r5.item() * 100))
        self._results['recall']['ir10'] = float("{:.3f}".format(ir_r10.item() * 100))
        self._results['recall']['tr1'] = float("{:.3f}".format(tr_r1.item() * 100))
        self._results['recall']['tr5'] = float("{:.3f}".format(tr_r5.item() * 100))
        self._results['recall']['tr10'] = float("{:.3f}".format(tr_r10.item() * 100))
        self._logger.info(self._results)
        return copy.deepcopy(self._results)

        Args:
            img_ids: a list of image IDs to evaluate on. Default to None for the whole dataset
        
datasets/evaluation/retrieval_evaluation.py