#python #python-3.x #tensorflow #dataset #generator
#python #python-3.x #tensorflow #набор данных #генератор
Вопрос:
Я хочу создать конвейер данных для обучения моделей TensorFlow. Данные хранятся в очень больших файлах HDF5 (250 ГБ).
Я написал конвейер, который работает для входных файлов меньшего размера, но в конечном итоге уничтожается ядром после использования слишком большого объема оперативной памяти подкачки (проверено с помощью мониторинга).
import tensorflow as tf
import h5py
class TestGenerator:
"""
Implements a generator that can be used by tf.data.Dataset.from_generator
to produce a dataset for any test data.
"""
def __init__(self, src, dset):
self.src = src
self.dset = dset
self.output_signature = (
tf.TensorSpec(shape=(2,), dtype=tf.uint64)
)
def __call__(self):
"""This is needed for tf.data.Dataset.from_generator to work."""
with h5py.File(self.src, 'r', swmr=True) as f:
for sample in f[self.dset]:
yield sample[0], sample[1]
gen = TestGenerator('h5file.h5', 'dset_path')
dataset = tf.data.Dataset.from_generator(
gen,
output_signature=gen.output_signature
)
for sample in dataset:
pass
Сначала я подумал, что это может быть проблемой модуля h5py, поэтому я протестировал его отдельно:
with h5py.File('h5file.h5', 'r', swmr=True) as f:
for sample in f['dset_path']:
pass
Это работает без проблем. Это приводит к выводу, что TensorFlow ответственен за проблему с памятью. Что меня раздражает, так это то, что я предположил, что TensorFlow извлекает необходимые данные «на лету» и, следовательно, позволяет избежать проблем с памятью.
Код протестирован и отлично работает для файлов меньшего размера. Я также тестировал версии, которые я использовал dataset.prefetch
перед итерацией, но с тем же результатом.
Загружает ли TensorFlow весь набор данных под капотом?
Ответ №1:
Если вы откроете диспетчер задач во время импорта tensorflow и создания вашей модели, покажет ли он чрезвычайно высокие значения зарезервированной памяти GPU?
Если это так, то это может быть не размер модели или данных, а тот факт, что tensorflow резервирует как можно больше памяти для всего обучения модели.
Для моего личного примера, мой 3080 имеет 10 ГБ выделенной памяти GPU, а tensorflow занял 9,7 ГБ.
Если это так, посмотрите на метод set_memory_growth на https://www.tensorflow.org/guide/gpu#limiting_gpu_memory_growth .
Использование этого уменьшило использование выделенной памяти GPU с 9,7 ГБ до 3,2 ГБ и 4 ГБ.
РЕДАКТИРОВАТЬ: я не уверен, в какой момент он будет стремиться выделить эту память, но если вы попытаетесь обучить модель и следить за производительностью диспетчера задач для графического процессора, вы должны выяснить, ведет ли он себя таким образом!
Комментарии:
1. Я перепробовал все предложения, но, к сожалению, это не сработало. Я думаю, это связано с тем, что данные TF не используют графический процессор и его память. Я отслеживаю распределение оперативной памяти в системе с
watch -n 1 free -m
помощью, и легко увидеть постепенную потерю доступного пространства, пока оно почти не достигнет нуля. Когда это происходит, процесс завершается ядром, а память освобождается.2. Ах, это больше похоже на то, что вы пытаетесь загрузить слишком много информации? Я точно не уверен, но можете ли вы дополнительно определить «RAM swap», о котором вы упоминаете? Потому что вашей памяти GPU потребуется 1) достаточно памяти для запуска модели и 2) достаточно памяти для получения данных, то есть копии из ОЗУ в память GPU?
3. Спасибо за вашу помощь, но, похоже, я столкнулся с ошибкой в базовой библиотеке h5py. То, что я пропустил в своем тестовом коде выше, заключалось в том, что я использую оператор среза для набора данных, например
f['dataset'][start:stop]
, для выбора подмножества данных. Похоже, что нарезка вызывает копирование всех выбранных данных в ОЗУ. Однако я нашел обходной путь, используяitertools.islice
on the iterable . Я оставлю эту тему открытой, поскольку это может помочь другим людям.