NumPy的字符串数组的内存使用量远远大于对象数组

2024-06-25 23:54:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我对Numpy还是个新手,在Numpy的dtypes上乱搞,发现特定于字符串的数据类型,也就是“U”,比对象类型占用更多的内存空间。说明这一事实的代码如下:

size= 100000
half_size = size//2

ind1 = np.arange(half_size)*2+1
ind2 = np.arange(half_size)*2

X = np.empty(size, dtype = 'object')

X[ind1] = 'smile'
X[ind2] = 'smile2'

W = np.empty(size, dtype = 'U6')
W[ind1] = 'smile'
W[ind2] = 'smile2'

print(X.nbytes)
print(W.nbytes)

结果如下:

800000
2400000

我的问题如下:

1)为什么会发生这种情况?为什么dtype='U6'占用的内存是dtype=object的3倍

2)有没有办法创建比dtype=object占用更少内存空间的string numpy数组?你知道吗

先谢谢你

编辑:我想解释一下,我的文章不是another post的副本,因为我的文章是关于内存使用的,而另一篇文章没有提到关于dtype='U'vs dtype='object'的内存使用

EDIT2:虽然我已经从another post中学到了一些新东西,但不幸的是另一篇文章没有回答我的问题,因为我的文章是关于内存使用的,而另一篇文章没有提到关于dtype='U'和dtype='object'的内存使用


Tags: 内存numpysizeobjectnp文章emptydtype
2条回答

sys.getsizeof是检查内存使用情况的一种方法,尽管您必须明智地使用它,了解它到底在测量什么。对于数组,它工作得相当好。你知道吗

没有任何元素的数组:

In [28]: sys.getsizeof(np.array([],'U6'))                                                            
Out[28]: 96
In [29]: sys.getsizeof(np.array(['smile','smile1'],'U6'))                                            
Out[29]: 144
In [30]: sys.getsizeof(np.array(['smile','smile1'],'S6'))                                            
Out[30]: 108

对于2个'U6'字符串,大小会跳跃48,4字节/字符*2个元素*6个字符/元素

对于bytestring数据类型(Py2的默认值),跳转是12,2*6。你知道吗

bytestring更紧凑,但请注意显示:

In [31]: np.array(['smile','smile1'],'S6')                                                           
Out[31]: array([b'smile', b'smile1'], dtype='|S6')

对于对象数据类型:

In [32]: sys.getsizeof(np.array(['smile','smile1'],object))                                          
Out[32]: 112

16个字节-2*8

但是再加上Python字符串的大小,额外的133字节

In [33]: sys.getsizeof('smile')                                                                      
Out[33]: 78
In [34]: sys.getsizeof('smile1')                                                                     
Out[34]: 55

对于bytestsrings:

In [36]: sys.getsizeof(b'smile')                                                                     
Out[36]: 38
In [37]: sys.getsizeof(b'smile1')                                                                    
Out[37]: 39

注意,当我添加一个字节字符时,大小会增加1。但当我添加一个unicode字符时,大小实际上会减小。unicode字符串的大小更难预测。我认为它可以为每个字符分配最多4个字节,但实际数量取决于字符和编码。通常我们不会尝试微管理Python的字符串处理。(除此之外,我相信Python还有一些字符串缓存。)

但当你分配

X[ind1] = 'smile'
X[ind2] = 'smile2'

在object情况下,创建两个Python字符串,并将引用(指针)分配给数组。所以内存使用是数组(1000…*8字节)加上这两个字符串的133字节。你知道吗

在“U6”情况下,每个元素占用4*6字节,而不管它是“smile”还是“smile1”(或“s”)。数组的每个元素使用相同的空间,而不管是否需要所有元素来表示字符串。你知道吗

一般来说,字符串不是numpy强度。当字符串具有相似的大小时,'U'或'S'数据类型的内存使用是可以的,但是如果字符串长度不同、重复和/或是unicode,则不太理想。numpy本身不做太多的字符串处理。np.char函数只是Python字符串方法的精简包装。你知道吗

pandas选择使用object数据类型而不是字符串数据类型。你知道吗

如果检查内存中每种数据类型的大小,则得到:

import numpy as np

dt = np.dtype('object')
print('object = %i bytes' % dt.itemsize)

dt = np.dtype('U6')
print('U6 = %i bytes' % dt.itemsize)

输出:

object = 8 bytes
U6 = 24 bytes

相关问题 更多 >