Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforcing in-memory transposition of a numpy array [duplicate]

I am interfacing a C library with python. I have arrays in numpy that I pass to the library using the ctypes attribute of the array.

At some point I need to provide an array to the C library, that is expected to be the transposed of the numpy array a I have. (Another way of putting it is that the C library does not accept a stride for the inner-most dimension). However when I pass a.T instead of a, nothing happens.

Indeed it seems that numpy does some sort of lazy transposition by simply swapping the strides:

import ctypes
import numpy as np
a = np.zeros((2, 3))
a.ctypes.strides_as(ctypes.c_longlong)[:]
# returns [24, 8]
a.T.ctypes.strides_as(ctypes.c_longlong)[:]
# return [8, 24]

My question is, how to enforce this transposition to happen in memory?

EDIT

I noticed that

a.T + np.zeros(a.T.shape)

reorders the memory like I want, but if there is a more elegant and explicit solution, I would still like to hear it.

(Also, interestingly,

a.T + np.zeros_like(a.T)

seems to not reorder memory).

like image 780
P-Gn Avatar asked Jul 10 '17 09:07

P-Gn


1 Answers

a.T, like a.transpose(), just affect the header and return views. You can check them with : a.T.flags.owndata, wich is False.

To actually transpose the data, the simplest way to make a copy : a=a.T.copy().

Making it in place is a harder task. You can do it this way :

a=np.arange(6).reshape(2,3).copy()
print(a,a.flags,id(a),sep='\n')

a.ravel()[:]=a.T.ravel()
a.shape=a.T.shape

print(a,a.flags,id(a),sep=('\n'))

Output :

[[0 1 2]
 [3 4 5]]
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
221212538640
[[0 3]
 [1 4]
 [2 5]]
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
221212538640

But with no warranty, since you write on data you read. It can fails without warning on big arrays.

like image 165
B. M. Avatar answered Sep 30 '22 19:09

B. M.