Repository: Lightning-AI/torchmetrics

Issue:
Sort currently does not support bool dtype on CUDA
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->


### To Reproduce

Steps to reproduce the behavior:

1. Run mAP on CUDA

<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->
```
RuntimeError: Sort currently does not support bool dtype on CUDA.
    self._call_and_handle_interrupt(
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 682, in _call_and_handle_interrupt
    return trainer_fn(*args, **kwargs)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 770, in _fit_impl
    self._run(model, ckpt_path=ckpt_path)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1193, in _run
    self._dispatch()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1272, in _dispatch
    self.training_type_plugin.start_training(self)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/plugins/training_type/training_type_plugin.py", line 202, in start_training
    self._results = trainer.run_stage()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1282, in run_stage
    return self._run_train()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1312, in _run_train
    self.fit_loop.run()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/base.py", line 145, in run
    self.advance(*args, **kwargs)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/fit_loop.py", line 234, in advance
    self.epoch_loop.run(data_fetcher)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/base.py", line 146, in run
    self.on_advance_end()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/epoch/training_epoch_loop.py", line 246, in on_advance_end
    self._run_validation()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/epoch/training_epoch_loop.py", line 341, in _run_validation
    self.val_loop.run()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/base.py", line 151, in run
    output = self.on_run_end()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/dataloader/evaluation_loop.py", line 133, in on_run_end
    self._on_evaluation_epoch_end()
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/loops/dataloader/evaluation_loop.py", line 240, in _on_evaluation_epoch_end
    self.trainer.call_hook(hook_name)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/pytorch_lightning/trainer/trainer.py", line 1483, in call_hook
    output = model_fx(*args, **kwargs)
  File "/home/swarm/tkupek/sync/minimal.py", line 101, in on_validation_epoch_end
    result = self.val_map.compute()  # GPUs get stuck here
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/torchmetrics/metric.py", line 380, in wrapped_func
    value = compute(*args, **kwargs)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/torchmetrics/detection/map.py", line 668, in compute
    overall, map, mar = self._calculate(self._get_classes())
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/torchmetrics/detection/map.py", line 513, in _calculate
    eval_imgs = [
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/torchmetrics/detection/map.py", line 514, in <listcomp>
    self._evaluate_image(img_id, class_id, area, max_detections, ious)
  File "/home/swarm/tkupek/venv/lib/python3.8/site-packages/torchmetrics/detection/map.py", line 374, in _evaluate_image
    ignore_area_sorted, gtind = torch.sort(ignore_area)
RuntimeError: Sort currently does not support bool dtype on CUDA.

Process finished with exit code 1
```

#### Code sample

See tests

### Expected behavior

Calculate mAP on CUDA without issues

### Environment

- PyTorch Version (e.g., 1.0):
- OS (e.g., Linux):
- How you installed PyTorch (`conda`, `pip`, source):
- Build command you used (if compiling from source):
- Python version:
- CUDA/cuDNN version:
- GPU models and configuration:
- Any other relevant information:

### Additional context

Raised by @tkupek 



Discussion:

Resolving patch:
diff --git a/torchmetrics/detection/map.py b/torchmetrics/detection/map.py
--- a/torchmetrics/detection/map.py
+++ b/torchmetrics/detection/map.py
@@ -407,7 +407,9 @@ def _evaluate_image(
         ignore_area = (areas < area_range[0]) | (areas > area_range[1])
 
         # sort dt highest score first, sort gt ignore last
-        ignore_area_sorted, gtind = torch.sort(ignore_area)
+        ignore_area_sorted, gtind = torch.sort(ignore_area.to(torch.uint8))
+        # Convert to uint8 temporarily and back to bool, because "Sort currently does not support bool dtype on CUDA"
+        ignore_area_sorted = ignore_area_sorted.to(torch.bool)
         gt = gt[gtind]
         scores = self.detection_scores[id]
         scores_filtered = scores[det_label_mask]
@@ -429,7 +431,7 @@ def _evaluate_image(
             for idx_iou, t in enumerate(self.iou_thresholds):
                 for idx_det in range(nb_det):
                     m = MAP._find_best_gt_match(t, nb_gt, gt_matches, idx_iou, gt_ignore, ious, idx_det)
-                    if m is not -1:
+                    if m != -1:
                         det_ignore[idx_iou, idx_det] = gt_ignore[m]
                         det_matches[idx_iou, idx_det] = True
                         gt_matches[idx_iou, m] = True


Test patch:
diff --git a/tests/detection/test_map.py b/tests/detection/test_map.py
--- a/tests/detection/test_map.py
+++ b/tests/detection/test_map.py
@@ -215,6 +215,19 @@ def test_empty_preds():
     metric.compute()
 
 
+_gpu_test_condition = not torch.cuda.is_available()
+
+
+@pytest.mark.skipif(_pytest_condition, reason="test requires that torchvision=>0.8.0 is installed")
+@pytest.mark.skipif(_gpu_test_condition, reason="test requires CUDA availability")
+def test_map_gpu():
+    """Test predictions on single gpu."""
+    metric = MAP()
+    metric = metric.to("cuda")
+    metric.update(_inputs.preds[0], _inputs.target[0])
+    metric.compute()
+
+
 @pytest.mark.skipif(_pytest_condition, reason="test requires that pycocotools and torchvision=>0.8.0 is installed")
 def test_empty_metric():
     """Test empty metric."""