2016-10-22 70 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的還是這樣?它將大幅提升性能和內存效率。 –