【发布时间】:2019-12-22 06:05:58
【问题描述】:
具体来说,我最近不得不处理一个大型数据集 (~3 GB),为了了解加载过程的速度(即运行 df = pd.read_csv(file)),我打开了一个任务管理器。
正如我所想,我看到我的 Python 进程的内存使用量不断上升。大约在它达到大约 3 GB 的时候,它已满载。逻辑。
然后,在完成了一些不涉及 Python 的其他任务之后,比如回复电子邮件或在线浏览,我注意到我的任务管理器中的 Python 内存使用率下降了很多,就好像我还没有加载任何数据一样。但我的笔记本内核仍在运行(没有中断)。
奇怪的是,即使在内存使用量降低之后,我的代码仍然可以正常工作:我可以通过运行以下示例来显示来自我的数据帧的信息:
df.loc[100000:101000,['col1','col2','col3']],
立即显示这 1000 行。
或者如果我运行:
df.info(),
这给了我这个:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3228691 entries, 0 to 3228690
Columns: 117 entries, first_column to last_column
dtypes: category(49), float64(51), object(17)
memory usage: 1.8+ GB
这很奇怪,因为当我运行 df.info(memory_usage='deep') 而不仅仅是 df.info() 时,它需要更长的时间,而且我可以在我的任务管理器中看到 Python 进程的内存使用量一直上升到大约 1.5 GB。这是输出:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3228691 entries, 0 to 3228690
Columns: 117 entries, first_column to last_column
dtypes: category(49), float64(51), object(17)
memory usage: 4.9 GB
同样,这很奇怪,因为它的内存使用量达到了 ~1.5 GB,但是输出给出了 4.9 GB 作为 ~3 GB 文件的内存使用量。
我猜 Python 不会将一段时间未使用的内容保存在内存中,但我很好奇这里的规则是什么?这是如何运作的?这是 Pandas 的内存管理过程,还是 Python 的内存管理过程?
【问题讨论】:
-
如果没有
deep选项,内存使用量是估计值,而不是实际内存量。这是报告虚拟内存,而不是物理 RAM,因此与内存中保存的内容无关。 -
@Barmar 这不是一个估计值,而是没有考虑到
dtype=object列中对其他 pyhton 对象的引用所占用的内存。我不认为它与虚拟内存有任何关系,它是itemsize * number_of_items的简单等式,但是当item类型为object时,它只是使用机器字(它只考虑指针,而不是对象被参考) -
顺便说一句,假设您的 pandas 数据帧需要大约 3 GB,因为您正在读取大约 3 GB 的 csv 文件,这不是一个好的假设。数据在 csv 中表示的方式(作为文本,因此取决于编码,通常每个字符大约 1 个字节)与在主存储器中表示的方式完全不同(作为占用恒定空间的浮点数,作为成熟的 python 对象,它需要 8 字节的指针开销,然后是大量的 python 对象开销,然后是字符串每个字符 1 个字节)
-
@juanpa.arrivillaga 文档特别指出这是一个估计值。我在下面的答案中复制了它。
-
我的意思是,估计和深度自省都在报告正在使用的虚拟内存量;非特权进程通常无法分辨虚拟内存的哪些部分实际上在 RAM 中。