Repository: numba/numba

Issue:
problem with `atomic.compare_and_swap`
<!--

Thanks for opening an issue! To help the Numba team handle your information
efficiently, please first ensure that there is no other issue present that
already describes the issue you have
(search at https://github.com/numba/numba/issues?&q=is%3Aissue).

-->

## Reporting a bug

<!--

Before submitting a bug report please ensure that you can check off these boxes:

-->

- [x] I have tried using the latest released version of Numba (most recent is
 visible in the change log (https://github.com/numba/numba/blob/main/CHANGE_LOG).
- [x] I have included a self contained code sample to reproduce the problem.
  i.e. it's possible to run as 'python bug.py'.

<!--

Please include details of the bug here, including, if applicable, what you
expected to happen!

-->

I am trying to use `atomic.compare_and_swap` with float32-s. I get the following error:

```
E                   numba.core.errors.TypingError: Failed in cuda mode pipeline (step: nopython frontend)
E                   No implementation of function Function(<class 'numba.cuda.stubs.atomic.compare_and_swap'>) found for signature:
E                    
E                    >>> compare_and_swap(array(float32, 1d, C), float32, float32)
E                    
E                   There are 2 candidate implementations:
E                     - Of which 2 did not match due to:
E                     Overload of function 'compare_and_swap': File: numba/cuda/cudadecl.py: Line 431.
E                       With argument(s): '(array(float32, 1d, C), float32, float32)':
E                      No match.
E                   
E                   During: resolving callee type: Function(<class 'numba.cuda.stubs.atomic.compare_and_swap'>)
E                   During: typing of call at /home/shauncutts/src/factfiber.ai/mlops/ingolstadt/tests/cudautil/test_mathutil.py (153)
E                   
E                   
E                   File "tests/cudautil/test_mathutil.py", line 153:
E                   def _dummy_kernel() -> None:
E                       <source elided>
E                       zero = np.float32(0)
E                       cuda.atomic.compare_and_swap(array, zero, zero)  # type: ignore
E                       ^
```
Source code:
```py
@cuda.jit  # type: ignore
def _dummy_kernel() -> None:
    array = cuda.shared.array(1, dtype=np.float32)  # type: ignore
    zero = np.float32(0)
    cuda.atomic.compare_and_swap(array, zero, zero)  # type: ignore
```





Discussion:
Thanks for the report - looks like the docs fail to mention that this is only supported for integer types: https://numba.readthedocs.io/en/latest/cuda/intrinsics.html?highlight=compare_and_swap

This mirrors CUDA C / C++: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#atomiccas

Once I have completed the patch in https://github.com/numba/numba/issues/6026#issuecomment-1273285104, the following workaround would work:

```python
@cuda.jit  # type: ignore
def _dummy_kernel() -> None:
    array = cuda.shared.array(1, dtype=np.float32)  # type: ignore
    zero = np.float32(0).view('i4')
    cuda.atomic.compare_and_swap(array, zero, zero)  # type: ignore
```

I'm not quite sure whether to create an implementation of atomic CAS for floats - @shaunc did you come across this for implementing a specific use case, or was it just something you noticed incidentally and kindly reported?
From triage meeting discussion: marking as a documentation issue.

Resolving patch:
diff --git a/numba/cuda/stubs.py b/numba/cuda/stubs.py
--- a/numba/cuda/stubs.py
+++ b/numba/cuda/stubs.py
@@ -501,6 +501,8 @@ class compare_and_swap(Stub):
         Conditionally assign ``val`` to the first element of an 1D array ``ary``
         if the current value matches ``old``.
 
+        Supported on int32, int64, uint32, uint64 operands only.
+
         Returns the current value as if it is loaded atomically.
         """
 


Test patch: