#python #aws-lambda #scipy #wav #audio-processing
Вопрос:
Я запускаю некоторый код Python (3.8) внутри функции AWS Lambda, используя scipy
lib. Сначала я прочитал wavfile в переменную:
source = scipy.io.wavfile.read('/tmp/letov.wav')
Похоже, он работает нормально , getsizeof(source)
возвращает 56
, как я понимаю, это означает, что переменная содержит некоторые данные.
Затем эта строка запускается, и скрипт зависает бесконечно:
audio_samples = source[1].tolist()
Почему?
Когда я запускаю это на локальном компьютере, все работает нормально (несколько секунд).
Но в Лямбде он достигает предела времени до 300 лет. Я также попытался увеличить лямбда-память со 128 Мб до 512 Мб, чтобы убедиться, что это не проблема с вычислительной мощностью, не повезло. Аудиофайл одинаков в обеих средах.
Комментарии:
1. Что вы получаете за
getsizeof(source)
(на локальном компьютере), когда используетеletov.wav
2.
56
, то же значение3. К вашему сведению:
wavfile.read
возвращает кортеж.getsizeof(source)
задает размер только структуры данных кортежа; он не включает размеры содержащихся в нем элементов. например.getsizeof((0, 0))
иgetsizeof((np.zeros(1000000), np.zeros(1000000))
оба возвращают 56.4. Насколько велик аудиофайл? На локальной машине, что такое
source[1].dtype
иsource[1].shape
?5. размер: 8,46 Мб, источник[1].Тип dtype: int16, источник[1].форма: (2219729, 2)
Ответ №1:
Из информации, представленной в комментариях, мы знаем, что source[1]
это массив numpy из 16-битных целых чисел с формой (2219729, 2). Память , необходимая для хранения фактического массива целых 2219729*2*2 = 8878916
чисел, составляет или около 8,5 Мб. Как вы сказали, чтение файла работает, и у вас достаточно оперативной памяти для хранения данных в памяти.
Проблема возникает при вызове .tolist()
метода в массиве. Это преобразует структуру данных массива в чистый вложенный список списков Python. То есть при выполнении audio_samples = source[1].tolist()
audio_samples
будет список Python длиной 2219729, и каждый элемент в этом списке будет списком Python длиной 2 , а каждый элемент во внутреннем списке будет целым числом Python (а не 16-битным целым числом NumPy). Для одного целого числа Python требуется 28 байтов (т. Е. getsizeof(1)
возвращается 28). Поэтому просто для хранения всех этих целых чисел Python (без учета структуры данных списка) вам понадобится 2219729 * 2 * 28 = 124304824
байт, или около 124 МБ. Кроме того, для самого внешнего списка потребуется около 17,8 Мб, а для каждого внутреннего списка потребуется 72 байта, поэтому для объединенной структуры данных списка Python потребуется около 178 МБ. Объедините это с памятью, необходимой для всех целых чисел Python, содержащихся в этих списках, и вы получите общую потребность в памяти около 302 МБ.
Мой совет: не преобразуйте свои образцы в чистую структуру данных Python с помощью этого tolist()
метода. Придерживайтесь массива NumPy source[1]
. То есть используйте
audio_samples = source[1]
а затем используйте массив NumPy audio_samples
в своих последующих вычислениях.
Комментарии:
1. Да, для этого требуется больше памяти, чем я думал. Когда я увеличил до 1 ГБ, он прошел, но в следующей строке была выдана ошибка:
Unable to allocate 339. MiB for an array with shape (5418, 4096) and data type complex128
. Затем я увеличил память до 2 ГБ, и все прошло. Так что в основном это была проблема с памятью. Спасибо за указание.