The following produces a C-contiguous numpy array:
import numpy
a = numpy.ones((1024,1024,5))
Now if I slice it, the result may not longer
To force a numpy array x
to be C-contiguous, without making unnecessary copies when it's already that way to begin with, you should use,
x = numpy.asarray(x, order='C')
Note, that if this array was not C-contiguous, it would probably be similar in terms of efficiency to x.copy(order='C')
. I don't think there is a way around it. You can't reorganize the alignment of an array in memory otherwise than by making a copy of the data to a new location.
Rewriting your code so it uses the sliced index first, as in numpy.ones((5,1024,1024))
seems to be the only reasonable way of optimizing this.
As things stand, any attempt to coerce the slice bn
to C contiguous order is going to create a copy.
If you don't want to change the shapes you're starting with (and don't need a
itself in C order), one possible solution is to start with the array a
in Fortran order:
>>> a = numpy.ones((1024, 1024, 5), order='f')
The slices are also then F-contiguous:
>>> bn = a[:, :, 0]
>>> bn.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
...
This means that the transpose of the slice bn
will be in C order and transposing does not create a copy:
>>> bn.T.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : False
...
And you can then hash the slice:
>>> hashlib.sha1(bn.T).hexdigest()
'01dfa447dafe16b9a2972ce05c79410e6a96840e'
This is a standard operation when interfacing numpy with C. Have a look at numpy.ascontiguousarray
x=numpy.ascontiguousarray(x)
is the proper way of dealing with it.
Use numpy.asfortranarray if you need fortran order.
As mentioned the function will copy if necessary. So there is no way around it. You can try rollaxis before your operation, such that the short axis is the first axis. This gives you a view on the array
In [2]: A=np.random.rand(1024,1024,5)
In [3]: B=np.rollaxis(A,2)
In [4]: B.shape
Out[4]: (5, 1024, 1024)
In [5]: B.flags
Out[5]:
C_CONTIGUOUS : False
F_CONTIGUOUS : False
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
In [6]: A.flags
Out[6]:
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
So rollaxis does not solve this either.