将大量 .data 加载到数组中的最快方法

Posted

技术标签:

【中文标题】将大量 .data 加载到数组中的最快方法【英文标题】:Fastest way to load huge .dat into array 【发布时间】:2014-10-21 08:31:38 【问题描述】:

我在 stackexchange 中广泛搜索了一个将巨大 (~2GB) .dat 文件加载到 numpy 数组中的巧妙解决方案,但没有找到合适的解决方案。到目前为止,我设法以非常快速的方式(

list=[]
f = open('myhugefile0')
for line in f:
    list.append(line)
f.close()

使用 np.loadtxt 会冻结我的计算机并需要几分钟才能加载(约 10 分钟)。如何将文件作为数组打开,而不会出现似乎瓶颈 np.loadtxt 的分配问题?

编辑:

输入数据是一个浮点数 (200000,5181) 数组。一行示例:

2.27069e-15 2.40985e-15 2.22525e-15 2.1138e-15 1.92038e-15 1.54218e-15 1.30739e-15 1.09205e-15 8.53416e-16 7.715236e-16 7.5836 16 8.81664e-16 1.09204e-15 1.27305e-15 1.58008e-15

等等

谢谢

【问题讨论】:

你有64位python吗?你有多少内存? 是的,我有 Canopy 64 位 Enthought 发行版。我的内存是 8GB。我也在使用 Spyder,我也想知道这是否是个问题。 您能否向我们展示您的输入数据样本?至少有几行。 @cacosomoza 你试过np.genfromtxt吗? 您是否考虑过将数据文件重写为更适合相对大数据(fits 或 hdf5 左右)的数据格式,因为对于这些东西,有专门编写的库来处理(相对) 大数据 【参考方案1】:

查看source,似乎numpy.loadtxt 包含很多代码来处理许多不同的格式。如果您有一个定义明确的输入文件,编写您自己的针对特定文件格式优化的函数并不难。像这样的东西(未经测试):

def load_big_file(fname):
    '''only works for well-formed text file of space-separated doubles'''

    rows = []  # unknown number of lines, so use list
    with open(fname) as f:
        for line in f:
            line = [float(s) for s in line.split()]
            rows.append(np.array(line, dtype = np.double))
    return np.vstack(rows)  # convert list of vectors to array

如果之前知道行数和列数,另一种解决方案可能是:

def load_known_size(fname, nrow, ncol)
    x = np.empty((nrow, ncol), dtype = np.double)
    with open(fname) as f:
        for irow, line in enumerate(f):
            for icol, s in enumerate(line.split()):
                x[irow, icol] = float(s)
    return x

这样,你不必分配所有的中间列表。

编辑:似乎第二种解决方案有点慢,列表理解可能比显式 for 循环更快。结合这两种解决方案,并使用 Numpy 进行从字符串到浮点数的隐式转换(现在才发现)的技巧,这可能会更快:

def load_known_size(fname, nrow, ncol)
    x = np.empty((nrow, ncol), dtype = np.double)
    with open(fname) as f:
        for irow, line in enumerate(f):
            x[irow, :] = line.split()
    return x

要获得进一步的加速,您可能必须使用一些用 C 或 Cython 编写的代码。我很想知道这些函数打开您的文件需要多长时间。

【讨论】:

感谢 Blas,这是一个很大的改进。刚刚尝试使用 1.9 Gb dat 文件 (200000,864) 浮点数。对于未知大小:CPU 时间:用户 1 分钟 24 秒,系统:5 秒,总计:1 分钟 29 秒挂壁时间:4 分钟 14 秒 对于已知大小:CPU 时间:用户 1 分钟 45 秒,系统:2.52 秒,总计:1 分钟 47 秒挂壁时间:2 分钟 12 秒很奇怪,第二个函数花了更多时间 如果有人没有在几天内发布更快的方法,我会将答案标记为解决方案 第二个可能较慢的一个原因是内部循环 (for icol, s ...) 是在 Python 中完成的,而对于第一个函数,内部循环是一个列表解析 ([float(s) for ...]),它在 C 中实现。您可以尝试一些混合解决方案,首先使用列表推导转换为浮点列表,然后使用x[irow, :] = line 设置预分配矩阵x 的完整行。 运行时序比较的顺序可能很重要。您的文件系统具有缓存,因此无论您如何处理文件,第二次读取文件都可能比第一次更快。

以上是关于将大量 .data 加载到数组中的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

从 MySQL 将数值数据加载到 python/pandas/numpy 数组中的最快方法

将数据加载到 Cassandra 列族的最快方法是啥

使用不同格式(csv、json、avro)将数据加载到 pd.DataFrame 的最快方法

将大型 CSV 文件加载到核心数据中的最快方法是啥

从文本文件加载数据然后将其存储到数据库中的最快方法

将 2x4 64b 结构的第一行加载到 AVX2 的 256b 寄存器中的最快方法是啥?