Эффективное объединение больших Numpy массивов - PullRequest
0 голосов
/ 04 мая 2020

Я запускаю процесс, который создает очень большое количество векторов объектов (например, numpy массивов) и объединяет их в один массив. В настоящее время этот процесс требует большого объема памяти, и я ищу более эффективный способ его использования.

В настоящее время я генерирую векторы функций в пакетах по 100000 и объединяю их вместе.

all_features = None

for i in range(0, num_entries, 100000):
    features = get_features(entries[i:i+100000]) # generate a batch of 100,000 feature vectors
    features = np.array(features)

    if all_features is not None:
        all_features = np.concatenate([all_features, features])
    else:
        all_features = features

    del features
    gc.collect()
* 1005 Я обнаружил, что итеративное объединение векторов объектов с последующим удалением промежуточного объекта features более эффективно, чем генерация всех объектов одновременно и объединение их всех одновременно. Я считаю, что это потому, что np.concatenate выделяет новый объект в памяти. (Попытка сгенерировать все векторы объектов одновременно, затем конкатенация увеличивает объем памяти).

При этом доходит до того, что для выполнения конкатенации в конце l oop все еще требуется около 30 ГБ память (которая сразу освобождается после запуска конкатенации).

В основном у меня достаточно памяти на моем экземпляре, чтобы сохранить полный набор функций, но память перепрыгивает из упаковки вещей в один массив, из-за чего мне не хватает память.

Есть ли более эффективный способ памяти?

Ответы [ 2 ]

1 голос
/ 04 мая 2020

Сделайте вашу get_features функцию генератором, а затем используйте np.fromiter для создания массива.

Простой пример

def gen_values():
    for i in range(1000000): 
        yield i

a = np.fromiter(gen_values(), dtype=int)

Вам необходимо указать dtype в np.fromiter и вы можете дополнительно указать количество элементов, получаемых от генератора, с помощью count. Хотя это и необязательно, гораздо лучше указать count, чтобы numpy мог предварительно выделить массив вывода, а не изменять его по требованию.

1 голос
/ 04 мая 2020

Если известен общий размер all_features, я бы предложил выделить его заранее all_features=np.zeros(...), а затем заполнить его в l oop. Таким образом вы избавляетесь от множественных перераспределений, удалений и вызовов np.concatenate ().

...