生成器和读取文件优化

NG

我有数千个二进制文件,我必须读取这些文件并将其存储在内存中才能处理数据。我已经有一个允许读取这些数据的函数,但我想改进它,因为它有点慢。

数据是这样组织的:

  • 1000 个立方体。
  • 每个立方体都写在 10 个二进制文件中。

目前我有一个读取函数,可以读取并返回一个 numpy 数组 (read_1_cube) 中的一个立方体。然后我遍历所有文件以提取所有多维数据集并将它们连接起来。

def read_1_cube( dataNum ):
    ### read the 10 subfiles and concatenate arrays
    N_subfiles = 10
    fames_subfiles = ( '%d_%d'%(dataNum,k) for k in range(N_subfiles) )
    return np.concatenate( [np.fromfile( open(fn,'rb'), dtype=float, count=N*N*N ).reshape((N,N,N)) for fn in fames_subfiles], axis=2 )

TotDataNum = 1000
my_full_data = np.concatenate( [read_1_cube( d ) for d in range( TotDataNum )], axis=0 )

我尝试使用生成器来限制使用的内存量。使用这些功能每个文件需要大约 2.5 秒,所以 1000 个文件需要 45 分钟,最后我将有 10000 个文件,所以这是不可行的(当然,我不会一次读取 10000 个文件,但是钢铁我如果 1000 个文件需要 1 小时,则无法工作)。

我的问题:

  • 你知道优化 read_1_cube 和生成 my_full_data 的方法吗?
  • 您确实看到了更好的方法(没有 read_1_cube)?
  • 另一种优化方式:您知道是否有可以在生成器上工作的连接函数(例如 sum()、min()、max()、list()...)?

编辑:下面讲np.concatenate @liborm的评论,我觉得其他同等功能(栈串连问题np.r_, np.stack, np.hstack好处是堆栈可以在输入中使用生成器。所以我尽可能用生成器推送,只在最后创建实际的数据数组。

def read_1_cube( dataNum ):
    ### read the 10 subfiles and retur cube generator
    N_subfiles = 10
    fames_subfiles = ( '%d_%d'%(dataNum,k) for k in range(N_subfiles) )
    return (np.fromfile( open(fn,'rb'), dtype=float, count=N*N*N ).reshape((N,N,N)) for fn in fames_subfiles)

def read_N_cube( datanum ):
    ### make a generator of 'cube generator'
    C = ( np.stack( read_1_cube( d ), axis=2 ).reshape((N,N,N*10)) for d in range(datanum) )
    return np.stack( C ).reshape( (datanum*N,N,N*N_subfiles) )

### The full allocation is done here, just once
my_full_data = read_N_cube( datanum )

它比第一个版本更快,第一个版本需要 2.4 秒读取 1 个文件,第二个需要 6.2 读取 10 个文件!

我认为没有太多优化的地方,但我相信还有更好的算法!

自由

为了获得良好的性能(通常),您需要尽可能少地分配 - 这应该事先只分配大数组,然后在读取期间分配每个小数组。使用stackconcatenate可能会(重新)分配内存并复制数据......

我没有数据来测试它,认为这是一个“伪代码”:

def read_one(d, i):
    fn = '%d_%d' % (d, i)
    return np.fromfile(open(fn,'rb'), dtype=float, count=N*N*N).reshape((N,N,N))

res = np.zeros((N * TotDataNum, N, N * N_subfiles))
for dat in range(TotDataNum):
    ax0 = N * dat
    for idx in range(N_subfiles):
        ax2 = N * idx
        res[ax0:ax0+N, :, ax2:ax2+N] = read_one(dat, idx)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章