numpy结构化数组中的子数组不是连续的

Sub-arrays in numpy structured array not c contiguous

我目前尝试将大量数组打包成 numpy 结构化数组。 根据to the numpy documentation

Sub-arrays always have a C-contiguous memory layout.

但是如果我创建一个结构化数组:

x = np.zeros((2,), dtype=[('a', (np.float64, 5)), ('b', (np.float64, 5))])
x['a'].flags
# Out: C_CONTIGUOUS : False
#      F_CONTIGUOUS : False
#      OWNDATA : False
#      ...

同时

x.flags
# Out: C_CONTIGUOUS : True
#      F_CONTIGUOUS : True
#      OWNDATA : True
#      ...

并使用 (1,) 的 "outer" 形状作为数组产生:

x = np.zeros((1,), dtype=[('a', (np.float64, 5)),('b',(np.float64, 7))])
x['a'].flags
# Out: C_CONTIGUOUS : True
#      F_CONTIGUOUS : False
#      OWNDATA : False
#      ...

省略 (1,) 会产生具有 ndim=1 和 c-contiguity 的数组。所以引用似乎是 True only for the rows of an structured array.

令我困惑的是,当我直接为每个子数组指定数组形状时,给出了连续性:

x = np.zeros((), dtype=[('a', (np.float64, (2, 5))), ('b', (np.float64, (2, 5)))])

x['a'].flags
#Out: C_CONTIGUOUS : True
#     F_CONTIGUOUS : False
#     OWNDATA : False

根据 numpy 文档的引述,我认为子数组 总是 具有 C 连续内存布局,但这似乎只适用于行或形状每个数组都给出了。
这种行为从何而来?正在定义 "outer" 形状(我不知道怎么称呼它...)告诉 numpy 制作 子数组 的行子数组,同时指定每个子数组的形状直接连续存储每个子数组?
当所有子数组的第一维相等而第二维不相等时,处理此问题的最佳方法是什么?我应该直接指定每个形状以使它们连续吗?

有了你的 dtype 数组内存将是

x[0]['a'], x[0]['b']
x[1]['a'], x[1]['b']
....

x的记录由字段'a'的5个元素组成,接着是字段'b'的5个元素,以此类推下一条记录。

当它说subarrays are C contiguous时,它指的是一条记录中一个字段中的元素布局。

跨记录的字段 'a' 视图将不连续 - 'b' 的元素将分隔不同记录的元素。

同样的事情适用于二维数组的列切片:

In [32]: w = np.zeros((2,10))
In [33]: w.flags
Out[33]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  ...
In [34]: w[:,:5].flags    # w[:,5:] elements are in between
Out[34]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  ...

当子数组为 2d 时(如上一个示例),此连续注释更相关:

In [35]: dt=np.dtype([('a', (np.float64, 5)), ('b', (np.float64, (2,2)))])
In [36]: x=np.zeros((2,2,),dt,order='F')
In [37]: x.flags
Out[37]: 
  C_CONTIGUOUS : False
  F_CONTIGUOUS : True

In [39]: x[0,0]['b'].flags
Out[39]: 
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False

虽然整个数组 F 是连续的,但 'b' 元素仍然是 'C' 连续的。


定义一个数组:

In [40]: x = np.array([(1,[2,3]),(4,[5,6])], dtype=[('a',int),('b',int,2)])
In [41]: x
Out[41]: array([(1, [2, 3]), (4, [5, 6])], dtype=[('a', '<i8'), ('b', '<i8', (2,))])

将数组视为简单的 int dtype(并非总是可能):

In [42]: x.view(int)
Out[42]: array([1, 2, 3, 4, 5, 6])

这些数字是连续存储在内存中的。但是 'b' 字段的值不是连续的:

In [44]: x['b']
Out[44]: 
array([[2, 3],
       [5, 6]])

'a' 的值介于:

In [47]: x['a']
Out[47]: array([1, 4])