簡體   English   中英

給定字節緩沖區、數據類型、形狀和步幅,如何創建 Numpy ndarray

[英]Given a byte buffer, dtype, shape and strides, how to create Numpy ndarray

我有一個緩沖區、數據類型、形狀和步幅。 我想創建一個重用緩沖區內存的 Numpy ndarray。

numpy.frombuffer它從緩沖區創建一個一維數組numpy.frombuffer用內存。 但是,我不確定我是否可以輕松安全地重塑它並設定步伐。

numpy.ndarray構造函數可以引用緩沖區,但我不確定它是否會重用內存或是否會復制它(文檔中不清楚)。

那么, numpy.ndarray構造函數會做我想要的嗎? 或者我可以用什么代替?


好的,所以我現在試圖弄清楚numpy.ndarray構造函數真正在做什么。 代碼在這里 它使用PyArray_BufferConverter來轉換緩沖區參數。 然后它會調用PyArray_NewFromDescr_int ,可以在這里看到。 如果數據在那里傳遞,它將fa->flags &= ~NPY_ARRAY_OWNDATA; .

正如@hpaulj 的評論中所述,您可以使用 stride_tricks 模塊來完成此操作。 你需要np.frombuffernp.lib.stride_tricks.as_strided

從 NumPy 數組中收集數據

In [1]: import numpy as np
In [2]: x = np.random.random((3, 4)).astype(dtype='f4')
In [3]: buffer = x.data
In [4]: dtype = x.dtype
In [5]: shape = x.shape
In [6]: strides = x.strides

重新創建 NumPy 數組

In [7]: xx = np.frombuffer(buffer, dtype)
In [8]: xx = np.lib.stride_tricks.as_strided(xx, shape, strides)

驗證結果

In [9]: x
Out[9]: 
array([[ 0.75343359,  0.20676662,  0.83675659,  0.99904215],
       [ 0.37182721,  0.83846378,  0.6888299 ,  0.57195812],
       [ 0.39905572,  0.7258808 ,  0.88316005,  0.2187883 ]], dtype=float32)

In [10]: xx
Out[10]: 
array([[ 0.75343359,  0.20676662,  0.83675659,  0.99904215],
       [ 0.37182721,  0.83846378,  0.6888299 ,  0.57195812],
       [ 0.39905572,  0.7258808 ,  0.88316005,  0.2187883 ]], dtype=float32)

In [11]: x.strides
Out[11]: (16, 4)
In [12]: xx.strides
Out[12]: (16, 4)

我會堅持使用frombuffer因為它直接用於此目的,並明確您在做什么。 下面是一個例子:

In [58]: s0 = 'aaaa'   # a single int32

In [59]: s1 = 'aaabaaacaaadaaae'  # 4 int32s, each increasing by 1

In [60]: a0 = np.frombuffer(s0, dtype='>i4', count=1)   # dtype sets the stride

In [61]: print a0
[1633771873]

In [62]: a1 = np.frombuffer(s, dtype='>i4', count=4)

In [63]: print a1
[1633771874 1633771875 1633771876 1633771877]

In [64]: a2 = a1.reshape((2,2))   # do a reshape, which also sets the strides

In [65]: print a2
[[1633771874 1633771875]
 [1633771876 1633771877]]

In [66]: a2 - a0     # do some calculation with the reshape
Out[66]: 
array([[1, 2],
       [3, 4]], dtype=int32)

有什么東西是你需要的嗎?

您可以使用任何一種方法 - 它們都不會生成副本:

s = b'aaabaaacaaadaaae'
a1 = np.frombuffer(s, np.int32, 4).reshape(2, 2)
a2 = np.ndarray((2, 2), np.int32, buffer=s)

print(a1.flags.owndata, a1.base.tostring())
# (False, b'aaabaaacaaadaaae')
print(a2.flags.owndata, a2.base)
# (False, b'aaabaaacaaadaaae')

請注意,這兩個數組都不能就地修改,因為它們由只讀內存支持:

a1[:] = 0  # ValueError: assignment destination is read-only

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM