簡體   English   中英

將numpy數組拆分為不相等的塊

[英]Split of numpy array into unequal chunks

在我的程序中,我用元素填充了一個大型的numpy數組,這些元素的數量我事先並不知道。 由於每次向numpy數組添加單個元素效率低下,因此我將其大小增加了用零初始化的長度為10000的塊。 這導致最終我有一個尾巴為零的數組。 我想要的是數組,數組的長度恰好是有意義的元素的數量(因為稍后我無法將零零與零值的實際數據點區分開)。 但是,直接復制切片會使RAM消耗增加一倍,這確實是不希望的,因為我的數組很大。 我研究了numpy.split函數,但是它們似乎只能將數組拆分為大小相等的塊,這當然不適合我。

我用以下代碼說明了這個問題:

import numpy, os, random

def check_memory(mode_peak = True, mark = ''):
    """Function for measuring the memory consumption (Linux only)"""
    pid = os.getpid()
    with open('/proc/{}/status'.format(pid), 'r') as ifile:
        for line in ifile:
            if line.startswith('VmPeak' if mode_peak else 'VmSize'):
                memory = line[: -1].split(':')[1].strip().split()[0]
                memory = int(memory) / (1024 * 1024)
                break
    mode_str = 'Peak' if mode_peak else 'Current'
    print('{}{} RAM consumption: {:.3f} GB'.format(mark, mode_str, memory))

def generate_element():
    """Test element generator"""
    for i in range(12345678):
        yield numpy.array(random.randrange(0, 1000), dtype = 'i4')

check_memory(mode_peak = False, mark = '#1 ')
a = numpy.zeros(10000, dtype = 'i4')
i = 0
for element in generate_element():
    if i == len(a):
        a = numpy.concatenate((a, numpy.zeros(10000, dtype = 'i4')))
    a[i] = element
    i += 1
check_memory(mode_peak = False, mark = '#2 ')
a = a[: i]
check_memory(mode_peak = False, mark = '#3 ')
check_memory(mode_peak = True, mark = '#4 ')

輸出:

#1 Current RAM consumption: 0.070 GB
#2 Current RAM consumption: 0.118 GB
#3 Current RAM consumption: 0.118 GB
#4 Peak RAM consumption: 0.164 GB

誰能幫助我找到不會嚴重影響運行時間或RAM消耗的解決方案?

編輯:

我嘗試使用

a = numpy.delete(a, numpy.s_[i: ])

以及

a = numpy.split(a, (i, ))[0]

但是,它導致內存消耗翻倍

numpy.split不必將數組拆分為相等大小的塊。 如果使用indices_or_sections參數,則可以給出一個整數列表,它將用於分割數組。 例如:

>>> x = np.arange(8.0)
>>> np.split(x, [3, 5, 6, 10])
[array([ 0.,  1.,  2.]),   # x[:3]
 array([ 3.,  4.]),        # x[3:5]
 array([ 5.]),             # x[5:6]
 array([ 6.,  7.]),        # x[6:10]
 array([], dtype=float64)] # x[10:]

終於我明白了。 實際上,不僅在修剪階段,而且在串聯過程中都消耗了額外的內存。 因此,在點#2輸出處引入峰值內存檢查:

#2 Peak RAM consumption: 0.164 GB

但是,有一個resize()方法,可以就地更改數組的大小/形狀:

check_memory(mode_peak = False, mark = '#1 ')
page_size = 10000
a = numpy.zeros(page_size, dtype = 'i4')
i = 0
for element in generate_element():
    if (i != 0) and (i % page_size == 0):
        a.resize(i + page_size)
    a[i] = element
    i += 1
a.resize(i)
check_memory(mode_peak = False, mark = '#2 ')
check_memory(mode_peak = True, mark = '#2 ')

這導致輸出:

#1 Current RAM consumption: 0.070 GB
#2 Current RAM consumption: 0.118 GB
#2 Peak RAM consumption: 0.118 GB

此外,由於沒有更多的重新分配,因此性能也得到了顯着改善。

暫無
暫無

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

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