Мне было интересно, если кто-нибудь мог бы посоветовать, как получить максимальную производительность от тензорного потока в настройке 4 GPU.
В качестве теста я создал две одинаковые сети (остаточная сеть 18-го уровня с небольшими банками фильтров (от 16 до 128) на входах 32×32. Размер пакета 512, 128 на GPU.). Один в MXNet и один из которых я смоделировал начальный пример.
Моя сеть MXNet может тренироваться со скоростью около 7 тыс. Примеров в секунду, когда тензорный поток способен только на 4,2 тыс. С фиктивными данными и 3,7 тыс. С реальными данными.
(при работе на 1 GPU число составляет 1,2 тыс. примеров в секунду против 2,1 тыс.)
В моем эксперименте у меня есть несколько вопросов в надежде ускорить процесс.
Использование GPU кажется довольно низким при обучении. Я заметил, что в техническом документе tenorflow есть поддержка запуска нескольких потоков на одном GPU. Возможно ли это в публичном релизе?
Есть ли в любом случае выполнять несколько операций поезда в одном исполнении session.run()
? Или есть асинхронное выполнение? Это позволит обновлять вес одновременно со следующим проходом вперед? Я пытался использовать 2 темы (как системы, так и с QueueRunners
х), но это только привело к замедлению. MXNet может увеличить скорость, выполняя обновление весовых коэффициентов на процессоре, так что графические процессоры можно использовать для следующей партии.
Сможет ли новая распределенная среда выполнения обойти некоторые из этих проблем, позволив мне запустить более одного рабочего на одной машине?
Есть ли что-то еще, что можно сделать?
Я знаю, что здесь есть много похожих вопросов о переполнении стека, но, хотя в процессе поиска я не смог найти решение своих проблем, которые я еще не пробовал.
Редактировать:
Я немного профилировал CUDA, чтобы посмотреть, какие дорогие ядра. Согласно моему пробегу, 21,4% времени проводится внутри:
void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorPaddingOp<Eigen::array<std::pair<int, int>,
unsigned long=4> const, Eigen::TensorMap<Eigen::Tensor<float const,
int=4, int=1, long>, int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)
и 20,0% времени было проведено в
void Eigen::internal::EigenMetaKernel_NonVectorizable<Eigen::TensorEvaluator
<Eigen::TensorAssignOp<Eigen::TensorMap<Eigen::Tensor<float, int=4, int=1, long>, int=16>,
Eigen::TensorBroadcastingOp<Eigen::array<int, unsigned long=4>
const, Eigen::TensorMap<Eigen::Tensor<float const, int=4, int=1, long>,
int=16> const > const > const, Eigen::GpuDevice>, long>(float, int=4)
Вне подписи я не совсем уверен, что они делают. Есть ли в этом смысл?
В дополнение к этому, анализ показывает низкий уровень параллелизма ядра, 0%, как и ожидалось.
Низкое использование вычислений — 34,9% (при условии, что это включает в себя время запуска и немного Python в цикле поезда. Всего около 32 секунд из 91. Это дает около 50% использования в тензорном потоке.)
Изменить 2:
Я приложил копию урезанного исходный код. В целом, хотя меня больше волнует вопрос 1-3, и я не хочу занимать слишком много времени.
Кроме того, я работаю в тензорном потоке, построенном из: f07234db2f7b316b08f7df25417245274b63342a
Изменить 3:
Обновлен до самого последнего тензорного потока (63409bd23facad471973b110df998782c0e19c06) того же кода, формата данных по умолчанию (NHWC), и это, похоже, значительно ускорило это.
По фальшивым данным 6,7к-6,8к (тепловая зависимость, я думаю?) Примеров второго 4гпу. 1gpu — 2.0к примеров в секунду.
Реальная производительность данных составляет около 4,9 тыс. Примеров в секунду для 4ГПУ. 1gpu — 1,7 тыс. Примеров в секунду.
Изменить 4:
Кроме того, я попробовал переключить форматы данных в BCHW. Я сделал преобразование по модели Ориентиры Сумита. Части свертки действительно были быстрее, но пакетная норма, кажется, все испортила. С наивная реализация (фиксируя ось и делая веса [1, C, 1,1] вместо [C,]) Я могу получать только 1,2 тыс. примеров в секунду на 4 GPU (поддельные данные). Где, как и в случае транспонирования до и после пакетной нормы, я могу получить 6,2 тыс. Примеров в секунду (поддельные данные). Все еще медленнее чем data_format NHWC.
Немного трудно диагностировать проблему производительности вашей программы, не видя код. Можно ли как-нибудь прочитать ваш тестовый код?
Показывать TensorPadding сверху немного странно. Я ожидаю, что Cudnn звонки должны быть в верхней части профиля. В любом случае, показ нам тестового кода будет полезен.
Других решений пока нет …