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.ascontiguousarray
或np.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
假设我们有一个 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.ascontiguousarray
或np.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