我正在使用numpy (1.13.1)和pandas (0.20.3),在Ubuntu 16.10上使用python 2.7或3.5(无论哪种都存在同样的问题)。
我正在研究pandas的内存处理(特别是当它复制或不复制数据时),并遇到了一个我不理解的重大内存问题。虽然我看过(很多)其他人关于其内存性能的问题,但我没有找到直接解决这个问题的任何问题。
具体来说,pandas分配的内存比我要求的要多得多。当我尝试仅分配具有特定大小列的DataFrame时,我注意到了一些非常奇怪的行为:
import pandas as pd, numpy as np
GB = 1024**3
df = pd.DataFrame()
df['MyCol'] = np.ones(int(1*GB/8), dtype='float64')
当我执行这段代码时,我发现我的 Python 进程实际上分配了 6GB 的内存(如果我要求 2GB,则为 12GB;如果我要求 3GB,则为 21GB;如果我要求 4GB,则我的计算机会崩溃 :-/),而不是预期的 1GB。起初我以为是 Python 在进行一些积极的预分配,但是如果我只构造 numpy 数组本身,每次得到的内存大小都恰好是我所请求的大小,无论是 1GB、10GB 还是 25GB 等。此外,更有趣的是,如果我稍微改变一下代码:
df['MyCol'] = np.ones(int(1*GB), dtype='uint8')
它分配了如此之多的内存,以至于导致我的系统崩溃(仅运行numpy调用就可以正确分配1GB的内存)。(编辑于2017/8/17:出于好奇,我今天尝试使用更新的pandas(0.20.3)和numpy(1.13.1)版本,以及升级到64GB的RAM。但运行此命令仍然有问题,分配了所有64(左右)GB可用内存。)
如果pandas复制数据并分配另一列来存储索引,则可以理解申请的内存加倍甚至三倍,但我无法解释实际上正在发生的事情。从浏览代码中也不太清楚。
我尝试以几种不同的方式构建数据框架,但都得到了相同的结果。考虑到其他人成功地使用此包进行大型数据分析,我不得不认为我做错了什么,尽管从文档中可以看出这是正确的。
你有什么想法吗?
一些额外的说明:
- 即使内存使用量很大,当调用memory_usage()时,pandas仍然(错误地)报告预期的数据大小(即,如果我分配一个1GB数组,它报告1GB,即使实际分配了6-10GB)。
- 在所有情况下,索引都很小(如memory_usage()所报告的那样,可能不准确)。
- 释放pandas数据框(df = None,gc.collect())并不能实际上释放所有内存。这种方法肯定存在泄漏。
df = pd.DataFrame({'MyCol':np.ones(int(1*GB), dtype=np.uint8)})
- MaxU - stand with Ukrainedf.index
占用多少空间?如果添加另一列,可能是相同的np.array
,内存使用会如何变化? - hpaulj