如何展平内存视图?
How to flatten a memoryview?
我有一个 memoryview
,步幅很大,如下所示:
>>> mv.strides
(96, 32, 8)
我想将此 memoryview
写入套接字,但我的网络库似乎需要 mv.strides == (1,)
的内存视图。 Python 中有没有办法将这个 memoryview
展平?
>>> flatten(mv).strides
(1,)
理想情况下,这既不会影响底层字节也不需要副本。我可以用 NumPy 做这个,但如果可能的话我宁愿保持通用。
编辑:这里有一些代码可以生成这样的内存视图
In [1]: import numpy as np
In [2]: x = np.ones((2, 3, 4))
In [3]: x.data
Out[3]: <memory at 0x7f371aa849a8>
In [4]: x.data.strides
Out[4]: (96, 32, 8)
澄清一下,您可能知道这一点,但我认为最好确保:
- strides元组的长度表示维数,所以
(1, )
和(8, )
都是一维的,(10, 2)
和(20, 1)
都是二维的。
- 对于 C 连续数组,strides 元组中的最后一个元素表示内存视图中项目的项目大小。这并不总是正确的:有时值会被填充然后它会大于实际的项目大小 - 但在大多数情况下它代表项目大小。
因此,您不仅希望将内存视图展平,还应该展平并且项目大小为 1。
在 Python 3.3 中添加了 memoryview.cast
方法,这使得扁平化数组变得微不足道:
cast(format[, shape])
Cast a memoryview to a new format or shape. shape defaults to [byte_length//new_itemsize], which means that the result view will be one-dimensional. The return value is a new memoryview, but the buffer itself is not copied. Supported casts are 1D -> C-contiguous and C-contiguous -> 1D.
The destination format is restricted to a single element native format in struct syntax. One of the formats must be a byte format (‘B’, ‘b’ or ‘c’). The byte length of the result must be the same as the original length.
所以它只有在转换为 char (c
)、unsigned char (B
) 或 signed chars (b
) 并且它是 C 连续的时才有效。
>>> import numpy as np
>>> memview = memoryview(np.ones((2, 3, 4)))
>>> memview.cast('b').strides # or 'B' or 'c'
(1, )
然而,这被展平并解释为 1 字节值。如果你只是想让它变平,你需要再次将它转换为原始类型:
>>> memview.cast('b').cast(memview.format)
这将是一维的,但不会有 (1, )
的步长,因为浮点数是 8 个字节(至少如果它是 float64
):
>>> memview.cast('b').cast(memview.format).strides
(8, )
我有一个 memoryview
,步幅很大,如下所示:
>>> mv.strides
(96, 32, 8)
我想将此 memoryview
写入套接字,但我的网络库似乎需要 mv.strides == (1,)
的内存视图。 Python 中有没有办法将这个 memoryview
展平?
>>> flatten(mv).strides
(1,)
理想情况下,这既不会影响底层字节也不需要副本。我可以用 NumPy 做这个,但如果可能的话我宁愿保持通用。
编辑:这里有一些代码可以生成这样的内存视图
In [1]: import numpy as np
In [2]: x = np.ones((2, 3, 4))
In [3]: x.data
Out[3]: <memory at 0x7f371aa849a8>
In [4]: x.data.strides
Out[4]: (96, 32, 8)
澄清一下,您可能知道这一点,但我认为最好确保:
- strides元组的长度表示维数,所以
(1, )
和(8, )
都是一维的,(10, 2)
和(20, 1)
都是二维的。 - 对于 C 连续数组,strides 元组中的最后一个元素表示内存视图中项目的项目大小。这并不总是正确的:有时值会被填充然后它会大于实际的项目大小 - 但在大多数情况下它代表项目大小。
因此,您不仅希望将内存视图展平,还应该展平并且项目大小为 1。
在 Python 3.3 中添加了 memoryview.cast
方法,这使得扁平化数组变得微不足道:
cast(format[, shape])
Cast a memoryview to a new format or shape. shape defaults to [byte_length//new_itemsize], which means that the result view will be one-dimensional. The return value is a new memoryview, but the buffer itself is not copied. Supported casts are 1D -> C-contiguous and C-contiguous -> 1D.
The destination format is restricted to a single element native format in struct syntax. One of the formats must be a byte format (‘B’, ‘b’ or ‘c’). The byte length of the result must be the same as the original length.
所以它只有在转换为 char (c
)、unsigned char (B
) 或 signed chars (b
) 并且它是 C 连续的时才有效。
>>> import numpy as np
>>> memview = memoryview(np.ones((2, 3, 4)))
>>> memview.cast('b').strides # or 'B' or 'c'
(1, )
然而,这被展平并解释为 1 字节值。如果你只是想让它变平,你需要再次将它转换为原始类型:
>>> memview.cast('b').cast(memview.format)
这将是一维的,但不会有 (1, )
的步长,因为浮点数是 8 个字节(至少如果它是 float64
):
>>> memview.cast('b').cast(memview.format).strides
(8, )