Правильное использование non_blocking в PyTorch = True для предварительной выборки данных

#python #python-3.x #deep-learning #pytorch

#python #python-3.x #глубокое обучение #pytorch

Вопрос:

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

  1. Передача данных на графический процессор с использованием data = data.cuda(non_blocking=True)
  2. Закрепите данные в памяти процессора с помощью train_loader = DataLoader(..., pin_memory=True)

Однако я не могу понять, как выполняется неблокирующая передача в этом официальном примере PyTorch, в частности, в этом блоке кода:

 for i, (images, target) in enumerate(train_loader):
        # measure data loading time
        data_time.update(time.time() - end)

        if args.gpu is not None:
            images = images.cuda(args.gpu, non_blocking=True)
        if torch.cuda.is_available():
            target = target.cuda(args.gpu, non_blocking=True)

        # compute output
        output = model(images)
        loss = criterion(output, target)
  

Не будет images.cuda(non_blocking=True) и target.cuda(non_blocking=True) должно быть завершено перед output = model(images) выполнением. Поскольку это точка синхронизации, images сначала она должна быть полностью передана на устройство CUDA, поэтому этапы передачи данных фактически больше не являются неблокирующими.

Поскольку output = model(images) это блокировка, images.cuda() и target.cuda() на следующей i итерации for цикла не произойдет, пока не будет вычислен вывод модели, что означает отсутствие предварительной выборки на следующей итерации цикла.

Если это правильно, каков правильный способ выполнить предварительную выборку данных в GPU?

Ответ №1:

Я думаю, что вы ошибаетесь в том, что output = model(images) это точка синхронизации. Похоже, что вычисления обрабатываются другой частью графического процессора. Цитата из официальных документов PyTorch:

Кроме того, как только вы закрепите тензор или хранилище, вы можете использовать асинхронные копии GPU. Просто передайте дополнительный non_blocking=True аргумент в to() или cuda() вызов. Это может быть использовано для перекрытия передачи данных вычислениями.

Комментарии:

1. Должно non_blocking=True применяться как к изображениям, так и к целевым объектам? Поскольку изображения будут использоваться в вычислениях, как это поможет?

2. @OmarAlSuwaidi Да для обоих, потому что torch может предварительно извлекать 2-й пакет, в то время как первый выполняет свои вычислительные шаги вперед / назад.

Ответ №2:

Чтобы правильно реализовать предварительную выборку GPU в PyTorch, вы должны преобразовать цикл for в цикл while.

Загрузчик данных следует преобразовать в итератор с помощью iter функции, например iterator = iter(loader) .

Используйте next(iterator) на каждом шаге внутри цикла while для получения следующего мини-пакета.

Завершение загрузки данных может быть обнаружено путем перехвата StopIteration из итератора.

Используйте флаг для завершения цикла while при поднятии StopIteration .