Python, очистить большой список эффективно - PullRequest
1 голос
/ 24 марта 2020

Мне нужно очистить огромный list, который содержит приблизительно 350 тыс. Сложных массивов. В основном это заняло 2 минуты, чтобы очистить его всеми 3 способами очистки list (del data_list[:], data_list.clear() или data_list = []).

Как предлагается в комментариях, я разработаю дело. Под «комплексными массивами» я подразумеваю ndarray комплексных чисел. Следующие коды воспроизводят регистр.

import numpy as np
data_list = [np.zeros((4, 408), dtype=complex) for _ in range(350000)]
data_list = []  # this takes fairly long time

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

Итак, есть ли эффективный способ очистки большого списка?

Любой совет может быть полезен. Действительно ценю это.


Вы можете сделать его массивом numpy?

  • Поскольку число массивов может варьироваться, я думаю, list лучше добавлять данные динамически. Поправьте меня, если я ошибаюсь.

ОБНОВЛЕНИЕ

С помощью @ 6502 мы обнаружили, что проблема на самом деле является потенциальной ошибкой с ядром Python на Windows.

1 Ответ

1 голос
/ 24 марта 2020

Самая длинная часть в вашем фрагменте кода занимает распределение (в моей системе 0,56 с), а не освобождение (в моей системе 0,07 с).

import numpy as np, time, gc 
print("1") 
start = time.time() 
#gc.disable() 
data_list = [np.zeros((4, 408), dtype=complex) for _ in range(350000)] 
mid = time.time() 
#gc.enable() 
print("2") 
data_list = []  # "this takes fairly long time" (doesn't for me)
end = time.time() 
print("3") 
print(mid-start, end-mid) 

Моя догадка равна было , так как из-за больших элементов сборщик мусора запускается много раз во время выделения l oop (не проверял) , но это не так; даже отключение сборки мусора вокруг выделения не ускоряет код в моей системе .

Создание единого массива с

 data = np.zeros((350000, 4, 408), dtype=complex)
 data = []

незамедлительно, так как это одна большая память Объект выделен и освобожден в одном go. Конечно, это не объект list, поэтому поведение не совсем то же самое.

Если ваш код занимает много времени при освобождении, возможно, проблема в перегрузке основной памяти (т. Е. В пейджинге). 350000x4x408 составляет около 500 миллионов, и это число комплексных чисел двойной точности будет принимать в массиве numpy около 9 ГБ (и намного больше, чем complex Python объектов).

Если вы этого не сделаете если у вас есть такой объем свободной оперативной памяти, то управление ею с использованием виртуальной памяти будет проблемой, и, действительно, наблюдаемым симптомом может быть то, что после завершения обработки требуется много времени, чтобы «вернуться назад» ко всем материалам, которые были выделены для освободите место для данных.

Если это так, то даже хранение всех ваших данных в одном блоке памяти не сильно ускорится (время, потраченное на восстановление отброшенных 9 ГБ, а не освобождение памяти) само по себе).

В системах Windows ущерб производительности системы может быть даже "постоянным" в случае входа в режим tra sh: другими словами, система может быть не в состоянии восстановить нормальную скорость до следующей перезагрузки. Это происходило много лет go (Windows XP), и я не использую Windows регулярно ... возможно, последние версии устранили проблему.

ОБНОВЛЕНИЕ

Как Вы протестировали скрипт, и все же освобождение занимает 2 минуты. Думаю, объяснение может быть в дистрибутиве python или numpy. Чтобы проверить, в чем проблема, вы можете заменить

 np.zeros((4, 408), dtype=complex)

на

 array.array("d", [0.0]) * (2*4*408))

, чтобы выделить тот же объем памяти, используя только стандартные Python объекты; если проблема остается, то проблема в ядре python, в противном случае она находится в numpy. В обоих случаях я бы отправил отчет об ошибке ... может быть, это известная проблема на windows, и ответ будет "wontfix", но кажется странным, поскольку освобождение в моей системе Linux занимает менее 1se c и моя система, похоже, не в 120 раз мощнее вашей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...