Максимизируйте производительность multi-gpu с тензорным потоком

Мне было интересно, сможет ли кто-нибудь посоветовать, как получить максимальную производительность из тензорного потока в настройке 4 GPU.

В качестве теста я создал две из той же сети (остаточная сеть 18-го уровня с небольшими банками фильтров (от 16 до 128) на 32х32 входах. Размер партии 512, 128 на графический процессор.). Один в MXNet и один, который я смоделировал начальный пример.

Моя сеть MXNet может обучаться примерно в 7 тыс. примеров в секунду, где тензорный поток способен только 4,2 тыс. с фиктивными данными и 3,7 с реальными данными.

(при запуске на 1 графическом процессоре число составляет 1,2 тыс. примеров в секунду против 2,1 тыс.)

В моем эксперименте у меня есть несколько вопросов в надежде ускорить процесс.

  • Использование GPU кажется довольно низким при обучении. Я заметил, что в белой бумаге tensorflow есть поддержка для запуска нескольких потоков на одном GPU. Возможно ли это в публичном выпуске?

  • Есть ли способ выполнить несколько операций поезда в одном выполнении session.run()? Или выполнить асинхронное выполнение? Это позволило бы обновлять весы одновременно с прохождением следующих партий? Я попытался использовать 2 потока (как для системы, так и для QueueRunners), но это только привело к замедлению. MXNet может увеличить скорость за счет загрузки обновлений веса на CPU, чтобы gpu можно было использовать для следующей партии.

  • Будет ли новое распределенное время выполнения обходить некоторые из этих проблем, разрешив мне запустить более одного рабочего на одной машине?

  • Есть ли что-то еще, что можно сделать?

Я знаю, что здесь есть несколько подобных вопросов при переполнении стека, но, хотя в моем поиске я не смог найти решение своих проблем, которые я еще не пробовал.

Edit:

Я сделал немного профилирования 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)

Выключить подпись Я не совсем уверен, что они делают. Имеют ли они смысл?

В дополнение к этому, анализ сообщает о низком ядре concurrency, 0%, как и ожидалось. И низкое использование вычислений - 34,9% (это включает время запуска и немного питона в контуре поезда. Примерно 32 секунды всего из 91. Это происходит примерно до 50% использования в тензорном потоке.)

Изменить 2:

Я прикрепил копию обрезанного исходного кода. В целом, хотя меня больше волнует вопрос 1-3 и не хочу брать слишком много времени вовремя.

Кроме того, я запускаю тензорный поток, построенный из: f07234db2f7b316b08f7df25417245274b63342a

Изменить 3:

Обновлен до последнего tensorflow (63409bd23facad471973b110df998782c0e19c06) того же кода, формат данных по умолчанию (NHWC), и это, казалось, ускорило это. На поддельные данные 6.7k-6.8k (термическая зависимость я думаю?) Примеры второй 4gpu. 1gpu - 2.0k примеры в секунду. Реальная производительность данных составляет около 4.9k примеров в секунду для 4gpu. 1gpu - 1.7k примеров в секунду.

Изменить 4:

Кроме того, я попробовал преобразовать форматы данных в BCHW. Я сделал преобразование, смоделированное с помощью тестов Soumith. Свертки были действительно быстрее, но, конечно, периодическая норма, которая, по-видимому, все испортила. Используя наивную реализацию (фиксируя ось и делая весы [1, C, 1,1] вместо [C]), я могу получить только 1,2k примеров второй - на 4 gpu (поддельные данные). Где, как и с транспозицией до и после нормы партии, я могу получить 6.2k примеры второй (поддельные данные). Все еще медленнее, чем данные NHWC data_format.

Ответ 1

Немного сложно диагностировать проблему с производительностью программы, не видя кода. Возможно ли нам как-то прочитать ваш тестовый код?

TensorPadding, показывающий сверху, немного странно. Я ожидаю, что вызовы cudnn должны быть в верхней части профиля. В любом случае, показывая нам тестовый код, будет полезно.