From 193d28d1f83d4e4c512e16909ac82a042c23ad2b Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Thu, 27 Nov 2025 14:05:19 +0000 Subject: [PATCH] {WIP] Follow-on from #612: try to align with NumPy Aims to align more closely with NumPy contiguity logic. The example in the commit message from #612 still runs correctly with this change. I think this needs a little more consideration for now. --- numba_cuda/numba/cuda/cudadrv/devicearray.py | 6 ++--- numba_cuda/numba/cuda/cudadrv/dummyarray.py | 25 ++++++++++---------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/numba_cuda/numba/cuda/cudadrv/devicearray.py b/numba_cuda/numba/cuda/cudadrv/devicearray.py index 188b2f5a2..cfd25b5ab 100644 --- a/numba_cuda/numba/cuda/cudadrv/devicearray.py +++ b/numba_cuda/numba/cuda/cudadrv/devicearray.py @@ -178,11 +178,9 @@ def _numba_type_(self): # of which will be 0, will not match those hardcoded in for 'C' or 'F' # layouts. - broadcast = 0 in self.strides and (self.size != 0) - - if self.flags["C_CONTIGUOUS"] and not broadcast: + if self.flags["C_CONTIGUOUS"]: layout = "C" - elif self.flags["F_CONTIGUOUS"] and not broadcast: + elif self.flags["F_CONTIGUOUS"]: layout = "F" else: layout = "A" diff --git a/numba_cuda/numba/cuda/cudadrv/dummyarray.py b/numba_cuda/numba/cuda/cudadrv/dummyarray.py index 165459545..071e35414 100644 --- a/numba_cuda/numba/cuda/cudadrv/dummyarray.py +++ b/numba_cuda/numba/cuda/cudadrv/dummyarray.py @@ -275,19 +275,11 @@ def _compute_layout(self): # 13661ac70). # https://github.com/numpy/numpy/blob/maintenance/1.19.x/numpy/core/src/multiarray/flagsobject.c#L123-L191 + flags = {"C_CONTIGUOUS": True, "F_CONTIGUOUS": True} + # Records have no dims, and we can treat them as contiguous if not self.dims: - return {"C_CONTIGUOUS": True, "F_CONTIGUOUS": True} - - # All 0-size arrays are considered contiguous, even if they are multidimensional - if self.size == 0: - return {"C_CONTIGUOUS": True, "F_CONTIGUOUS": True} - - # If this is a broadcast array then it is not contiguous - if any([dim.stride == 0 for dim in self.dims]): - return {"C_CONTIGUOUS": False, "F_CONTIGUOUS": False} - - flags = {"C_CONTIGUOUS": True, "F_CONTIGUOUS": True} + return flags # Check C contiguity sd = self.itemsize @@ -342,7 +334,16 @@ def __getitem__(self, item): arr = Array(dims, self.itemsize) if newshape: - return arr.reshape(*newshape)[0] + # "A" order is required here so that the reshape can read and write + # the elements in fortran-like index order if the array is + # fortran-contiguous, and in C-like order otherwise. Otherwise, we + # end up reshaping fortran-contiguous arrays to C-contiguous, + # transposing indices in the process. + # + # See the NumPy reshape documentation of the order argument for a + # description of the behaviour this is following: + # https://numpy.org/doc/stable/reference/generated/numpy.reshape.html + return arr.reshape(*newshape, order="A")[0] else: return Element(arr.extent)