簡體   English   中英

numpy Loadtxt 函數似乎消耗了太多內存

[英]numpy Loadtxt function seems to be consuming too much memory

當我使用 numpy.loadtxt 加載數組時,它似乎占用了太多內存。 例如

a = numpy.zeros(int(1e6))

導致內存增加約 8MB(使用 htop,或僅 8bytes*1million \\approx 8MB)。 另一方面,如果我保存然后加載這個數組

numpy.savetxt('a.csv', a)
b = numpy.loadtxt('a.csv')

我的內存使用量增加了大約 100MB! 我再次用 htop 觀察到了這一點。 這是在 iPython shell 中以及使用 Pdb++ 單步執行代碼時觀察到的。

知道這里發生了什么嗎?

閱讀 jozzas 的回答后,我意識到如果我提前知道數組大小,如果說 'a' 是一個 mxn 數組,那么有一種更高效的內存方式來做事情:

b = numpy.zeros((m,n))
with open('a.csv', 'r') as f:
    reader = csv.reader(f)
    for i, row in enumerate(reader):
        b[i,:] = numpy.array(row)

將這個浮點數組保存到一個文本文件會創建一個 24M 的文本文件。 當您重新加載它時,numpy 會逐行瀏覽文件,解析文本並重新創建對象。

我希望在這段時間內內存使用量會激增,因為 numpy 在到達文件末尾之前不知道結果數組需要多大,所以我希望至少有 24M + 8M + 其他使用的臨時內存。

這是 numpy 代碼的相關部分,來自/lib/npyio.py

    # Parse each line, including the first
    for i, line in enumerate(itertools.chain([first_line], fh)):
        vals = split_line(line)
        if len(vals) == 0:
            continue
        if usecols:
            vals = [vals[i] for i in usecols]
        # Convert each value according to its column and store
        items = [conv(val) for (conv, val) in zip(converters, vals)]
        # Then pack it according to the dtype's nesting
        items = pack_items(items, packing)
        X.append(items)

    #...A bit further on
    X = np.array(X, dtype)

這種額外的內存使用不應該是一個問題,因為這只是 python 的工作方式——雖然你的 python 進程似乎使用了 100M 的內存,但它在內部保持了哪些項目不再使用的知識,並將重新使用它記憶。 例如,如果您要在一個程序(保存、加載、保存、加載)中重新運行此保存-加載過程,您的內存使用量不會增加到 200M。

這是我最終為解決此問題所做的工作。 即使您事先不知道形狀,它也能工作。 這首先執行轉換為浮點數,然后組合數組(與@JohnLyon 的答案相反,后者組合字符串數組然后轉換為浮點數)。 這對我來說使用的內存少了一個數量級,盡管可能會慢一些。 但是,我確實沒有使用np.loadtxt所需的內存,所以如果你沒有足夠的內存,那么這會更好:

def numpy_loadtxt_memory_friendly(the_file, max_bytes = 1000000, **loadtxt_kwargs):
    numpy_arrs = []
    with open(the_file, 'rb') as f:
        i = 0
        while True:
            print(i)
            some_lines = f.readlines(max_bytes)
            if len(some_lines) == 0:
                break
            vec = np.loadtxt(some_lines, **loadtxt_kwargs)
            if len(vec.shape) < 2:
                vec = vec.reshape(1,-1)
            numpy_arrs.append(vec)
            i+=len(some_lines)
    return np.concatenate(numpy_arrs, axis=0)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM