有效地将numpy数组写入二进制文件

Posted

技术标签:

【中文标题】有效地将numpy数组写入二进制文件【英文标题】:Write numpy array to binary file efficiently 【发布时间】:2018-08-16 18:38:29 【问题描述】:

我需要一个高效的解决方案来将大量数据写入二进制文件。目前我使用 numpy 方法.tofile,它消耗了大部分运行时。我的 MWE:

import numpy as np

def writeCFloat(f, ndarray):
    np.asarray(ndarray, dtype=np.float32).tofile(f)
def writeCInt(f, ndarray):
    np.asarray(ndarray, dtype=np.int32).tofile(f)
def writeC80(f, string):
    np.asarray(string, dtype='a80').tofile(f)

if __name__ == "__main__":
    f = open('test.out', mode='wb')
    ndarray = np.zeros((10000,10000))

    writeCInt(f, ndarray)
    writeCFloat(f, ndarray)
    writeC80(f, 'coordinates')

那么有没有比当前解决方案更有效的方法呢?提前致谢。

【问题讨论】:

考虑到您的代码中没有显式循环,并且asarray 的文档说如果输入已经是 ndarray,则不执行复制。,我想没有更快的方法。 为什么当前的解决方案太慢了?您是否有基准表明 python 可以实现更高的 IO 率,或者这是一个需要实时写入大量数据的脚本? 感谢您的回复。我目前正在做的是读取一个大型二进制文件(~40 Gb),然后将数据写回另一个二进制文件。我分析了python脚本,发现大部分时间都花在.tofile上。所以我想知道通过将数组、字符串等写入二进制文件的替代方法是否有改进的空间? 也许dask 适合您?一般来说,并行性可以让您加快速度,那么问题是您将如何实现它,但这取决于您的用例的细节。 我也觉得不错。您还可以考虑 pandas 提供的各种选项(如 HDF、羽毛或镶木地板)和 dask。 【参考方案1】:

您可以使用dask 并行运行此操作。这还允许您扩展超出单个线程的内存限制。

根据您的用例和您希望数据最终使用的文件类型,您可以执行以下操作:

MCVE

import numpy as np
import dask.array as da

def writeCFloat_dask(ndarray):
    da.from_array(ndarray).astype('float32').to_zarr('float32.zarr')
def writeCInt_dask(ndarray):
    da.from_array(ndarray).astype('int32').to_zarr('int32.zarr')
def writeC80_dask(string):
    da.from_array(string).astype('a80').to_zarr('a80.zarr')


if __name__ == "__main__":
    ndarray = np.zeros((100000,10000))

    writeCInt_dask(ndarray)
    writeCFloat_dask(ndarray)
    writeC80_dask('coordinates')

或者,如果您想将所有数组写入单个文件,您可以使用以下命令写入 HDF5:

def returnCFloat_dask(ndarray):
    return da.from_array(ndarray).astype('float32')
def returnCInt_dask(ndarray):
    return da.from_array(ndarray).astype('int32')
def returnC80_dask(string):
    return da.from_array(string).astype('a80')

if __name__ == "__main__":
    ndarray = np.zeros((100000,10000))

    da_float = returnCFloat_dask(ndarray)
    da_int = returnCInt_dask(ndarray)
    da_string = returnC80_dask('coordinates')

    da.to_hdf5('test-out.hdf5', '/float': da_float, '/int': da_int, '/string': da_string)

请参阅documentation on writing arrays to binary file types with Dask 了解更多信息。

【讨论】:

以上是关于有效地将numpy数组写入二进制文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在python 3中有效地将原始字节写入numpy数组数据

Numpy | 23 IO

在磁盘上保留 numpy 数组的最佳方法

Numpy数组的保存与加载

将 bz2 压缩二进制文件导入为 numpy 数组

python利用numpy存取文件