numpy 数组的属性

Properties of numpy array

假设我们有一个 numpy 数组。

a = np.array([[1,2,3],[4,5,6], [7,8,9]])

现在,如果我想提取第 0 列和第 2 列,则需要执行类似

的操作
b = a[:, [0, 2]]

但是,如果我们尝试通过执行 b.flags 来查找 b 的属性,我们会得到

C_CONTIGUOUS : False
F_CONTIGUOUS : True

可以看出,原来是C_contiguous的数组a自动转换为F_contiguous。如果我 运行 我的代码在单核上,这通常不会造成任何问题。但是,如果我使用 mpi4py 将数据分散到多个内核,它必须是 C_contiguous 否则分散是不正确的。

我的问题是如何避免 'b' 自动转换为 F_contiguous?

谢谢,

SLB

您可以使用np.ascontiguousarraynp.require来确保b在C序中:

b = np.ascontiguousarray(b)

或:

b = np.require(b, requirements='C')

首先,您可以通过将 b 复制到新数组来获得 C 连续版本:fixedb = b.copy().

至于为什么会这样,这可能是基本和高级索引混合的有效实现。看起来像从 a 复制时创建了一个隐藏数组,然后通过使其成为该隐藏数组的 F-连续视图来创建 b

a

#array([[1, 2, 3],
#       [4, 5, 6],
#       [7, 8, 9]])

a.base

#None
# means a is the original array

b = a[:, [0, 2]]

#array([[1, 3],
#       [4, 6],
#       [7, 9]])

b.base

#array([[1, 4, 7],
#       [3, 6, 9]])
# b is NOT the original array
# and the original array isn't a either

fixedb = b.copy()
#array([[1, 3],
#       [4, 6],
#       [7, 9]])

fixedb.base

#None
# new array is original, and by default copy makes C-contiguous

我只是猜测,但我认为 F_CONTIGUOUS 是由于 numpy 处理多列切片的方式。您还会在 b.flags 中看到标志 OWNDATA: False,这表明 b 是另一个数组的视图(尽管在本例中不是 a 的视图),但是相反:

>>> b.base
array([[1, 4, 7],
       [3, 6, 9]])

带有标志:

>>> b.base.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
...

这向我表明,numpy 对数组进行切片的方式是创建一个足够大的空数组来容纳列,然后将列一一复制到数组中,如:

>>> b.base.ravel()
array([1, 4, 7, 3, 6, 9])

但是通过将数组视为 F 连续而不是 C 连续,它将按列表示数据。

如果您想要一个包含相同形状和数据的新 C 连续数组,您可以简单地复制视图:

>>> c = b.copy()
>>> c.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : False
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False