2016-10-22 68 views
-1

我必须阅读大约300个文件才能创建与以下代码段的关联。鉴于这种关联,我必须在记忆中阅读它们。提高以下python代码的效率(内存/时间)

with util.open_input_file(f) as f_in: 
    for l in f_in: 
     w = l.split(',') 
     dfm = dk.to_key((idx, i, int(w[0]), int(w[1]))) <-- guaranteed to be unique for each line in file. 
     cands = w[2].split(':') 
     for cand in cands: 
      tmp_data.setdefault(cand, []).append(dfm) 

然后我需要这种格式上面写出来的数据结构:

k1, v1:v2,v3.... 
k2, v2:v5,v6... 

我使用以下代码:

# Sort/join values. 
    cand2dfm_data = {} 
    for k,v in tmp_data.items(): 
     cand2dfm_data[k] = ':'.join(map(str, sorted(v, key=int))) 
    tmp_data = {} 

    # Write cand2dfm CSV file. 
    with util.open_output_file(cand2dfm_file) as f_out: 
     for k in sorted(cand2dfm_data.keys()): 
      f_out.write('%s,%s\n' % (k, cand2dfm_data[k])) 

由于我必须处理的显著数文件,我正在观察两个问题:

  1. 用于存储的内存tmp_data非常大。在我的使用情况下,处理300个文件,它使用42GB。

  2. 写出CSV文件需要很长时间。这是因为我在每个项目()(约2.2M)上调用write()。此外,输出流使用gzip压缩器来节省磁盘空间。

在我的使用情况下,数字保证是32位无符号。

问:

  1. 为了实现内存减少,我认为这将是最好使用一个32位int来存储数据。我应该使用ctypes.c_int()将值存储在dict()(现在它们是字符串)还是有更好的方法?

  2. 为了加速写入,我应该写入一个StringIO对象,然后将其转储到一个文件或有更好的方法吗?

  3. 或者,也许有更好的方法来完成上述逻辑而不读取内存中的所有内容?

+3

如果你的代码运行没有错误,一个更好的地方可以问[codereview.se]。 – usr2564301

回答

2

很少有想法。

  1. 当前您在内存中多次复制数据。 您首次将它加载到tmp_data,然后将所有内容复制到cand2dfm_data,然后通过调用sorted(cand2dfm_data.keys())来创建密钥列表。

    为了减少内存使用:

    • 摆脱tmp_data的,分析和数据直接写入到cand2dfm_data

    • cand2dfm_data元组的列表,而不是字典

    • 使用cand2dfm_data.sort(...)而不是sorted(cand2dfm_data)以避免创建新列表

  2. 为了加快处理速度:

    • 转换键成整数,以提高分选性能(这将减少存储器使用以及)

    • 将数据写入磁盘中的块,例如100或500或1000条记录中一气呵成,这应该提高I \ O性能有点

  3. 使用profiler找到其他的性能瓶颈

  4. 如果使用了上面的优化内存占用仍然会太大,那么可以考虑使用磁盘备份的存储,用于存储和分拣的临时数据,例如SQLite

+0

最重要的是,如果您正在使用数字数据的工作,不是为什么不使用NumPy的还是这样?它将大幅提升性能和内存效率。 –