强制执行 numpy 数组的内存转置

P-G*_*-Gn 6 python ctypes numpy

我正在将一个 C 库与 python 接口。我在 numpy 中有数组,我使用ctypes数组的属性传递给库。

在某些时候,我需要向 C 库提供一个数组,这应该是a我拥有的 numpy 数组的转置。(另一种说法是,C 库不接受最内层维度的步幅)。但是,当我通过a.T而不是 时a,什么也没有发生。

事实上,numpy 似乎通过简单地交换步幅来进行某种懒惰的换位:

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]
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何强制这种换位发生在内存中?

编辑

我注意到

a.T + np.zeros(a.T.shape)
Run Code Online (Sandbox Code Playgroud)

像我想要的那样重新排列内存,但如果有更优雅和明确的解决方案,我仍然希望听到它。

(另外,有趣的是,

a.T + np.zeros_like(a.T)
Run Code Online (Sandbox Code Playgroud)

似乎没有重新排序内存)。

B. *_* M. 4

a.T,就像 a.transpose(),只影响标题和返回视图。您可以使用 : 来检查它们a.T.flags.owndata,即False.

要实际转置数据,最简单的方法是制作副本: a=a.T.copy()

使其到位是一项艰巨的任务。你可以这样做:

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'))
Run Code Online (Sandbox Code Playgroud)

输出 :

[[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
Run Code Online (Sandbox Code Playgroud)

但没有任何保证,因为您在读取的数据上写入。在大型阵列上,它可能会失败而不发出警告。