python 使用“broadcast_to”进行广播后,numpy数组中的“nbytes”值错误

u3r8eeie  于 2023-01-04  发布在  Python
关注(0)|答案(1)|浏览(175)

我刚注意到:

import numpy as np
import sys

arr = np.broadcast_to(0, (10, 1000000000000))
print(arr.nbytes)  # prints "80000000000000"
print(sys.getsizeof(arr))  # prints "120"

这是一个bug还是预期行为?即,nbytes是否意味着保存“逻辑”字节的数量,而不是0步?

p1tboqfb

p1tboqfb1#

虽然我没有看到它的文档,但nbytes看起来确实像是shape和itemsize的乘积,或者arr.size*arr.itemsize
在所有的例子中,我都看到nbytes使用了shape/size数组,而不是base,所以我不会过多地阅读文档中使用的“consumed”。
您的示例:

In [117]: arr = np.broadcast_to(0,(1,2,3))
In [119]: arr.shape, arr.strides, arr.nbytes
Out[119]: ((1, 2, 3), (0, 0, 0), 24)
In [120]: arr.base
Out[120]: array(0)
In [121]: arr.base.nbytes
Out[121]: 4

广播数组是一个小得多的数组的view; nbytes反映其自身的形状,而不是基底的形状。
再举一个例子,其中view是基的子集:

In [122]: np.arange(100).nbytes
Out[122]: 400
In [123]: np.arange(100)[::4].nbytes
Out[123]: 100

broadcast_to的代码可以在np.lib.stride_tricks._broadcast_to中查看,它使用np.nditer生成新视图。
sys.getsizeof可以合理地返回数组的内存使用情况及其on数据(即baseNone)。它不提供任何有关view的有用信息。

滑动窗口

另一个用于创建“更大”数组的跨步技巧示例:

In [180]: arr = np.arange(16).reshape(4,4).copy()
In [181]: arr.shape, arr.strides, arr.nbytes
Out[181]: ((4, 4), (16, 4), 64)

In [182]: res = np.lib.stride_tricks.sliding_window_view(arr,(2,2))    
In [183]: res.shape, res.strides, res.nbytes
Out[183]: ((3, 3, 2, 2), (16, 4, 16, 4), 144)

它是原始的(4,4)arrview

In [184]: res.base
Out[184]: <numpy.lib.stride_tricks.DummyArray at 0x1fa8e7cc730>
In [185]: res.base.base
Out[185]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
In [186]: res.base.base is arr
Out[186]: True

相关问题