Профессиональные GPU в серверах позиционируются как устройства для высокопроизводительных вычислений, систем искусственного интеллекта и рендеринговых ферм для 3D-графики. Стоит ли их применять для энкодинга, или это стрельба из пушки по воробьям? Попробуем разобраться.  

Для работы с многопоточным видео достаточно мощностей современных CPU и решений наподобие Intel Quick Sync. Более того, некоторые специалисты считают, будто загрузка профессиональных GPU декодингом и энкодингом — пустая трата ресурсов. Для потребительских видеокарт количество входящих потоков специально ограничивают до двух-трех, хотя мы уже убедились, что небольшое шаманство с драйвером позволяет это ограничение обойти. В предыдущей статье тестировались бытовые видеокарты, а сейчас мы займемся более серьезными — NVIDIA RTX A4000

Подготовка к тестированию

Что делать, если вывод lscpu выдает вам что-то вроде AMD Ryzen 9 5950X 16-Core Processor, но в компьютер вставлена NVIDIA RTX A4000 с 16 ГБ оперативной памяти, а вы хотите перекодировать и записать поток с нескольких сетевых камер? Информация с них обычно поступает через http, rtp или rtsp, и наша задача — поймать эти потоки, перекодировать их в нужный формат и записать каждый в отдельный файл.

Для проверки мы в HOSTKEY создали небольшой тестовый стенд с указанной выше конфигурацией CPU/GPU без специальной оптимизации и 32 ГБ оперативной памяти. На нем через FFmpeg мы будем принимать мультикаст-вещание в форматах http и rtsp (использован видеофайл bbb_sunflower_1080p_30fps_normal.mp4 из деморепозитория Blender), декодировать его в разном количестве потоков FFmpeg и записывать каждый из них в отдельный файл. Как видно из названия, мы принимаем поток в формате 1080p (30 кадров в секунду). Энкодинг будет применяться только к видео, а звуковые потоки пойдут без изменения.

Также несущественно, берем мы один входящий поток и имитируем его мультипоточность или параллельно обрабатываем несколько потоков. Работа с сетью и текущие процессы на тестовом стенде отнимают менее 1% ресурсов CPU, поэтому можно считать, что основную нагрузку на процессор и дисковую подсистему даст именно энкодинг.

Все дальнейшее повествование будет вестись для вещания через http, поскольку результаты для потока rtsp оказались сравнимыми. Чтобы не плодить множество консолей терминала на сервере, для теста были созданы простые bash-скрипты, в которые при запуске передается требуемое количество инстансов FFmpeg, перекодирующих видеопоток в h264.

Энкодинг на голом CPU:

#!/bin/bash                                                                                                          

for (( i=0; i<$1; i++ )) do                                                                                          

ffmpeg -i http://XXX.XXX.XXX.XXX:5454/ -an -vcodec h264 -y Output-File-$i.mp4 &                      

done  

На GPU мы будем использовать возможности видеокарты через NVENC (как собрать FFmpeg с его поддержкой, мы рассказывали в первой статье цикла):

#!/bin/bash                                                                                                          

for (( i=0; i<$1; i++ )) do                                                                                          

ffmpeg -i http://XXX.XXX.XXX.XXX:5454/ -an -vcodec h264_nvenc -y Output-File-$i.mp4 &               

done 

Скрипты запускают в цикле мультикаста и ловят в сети нашего кролика. Предварительно стоит проверить через тот же vlc или ffplay, что поток реально вещается. Результат мы будем оценивать по загрузке CPU/GPU, утилизации памяти и качеству записываемого видео, где главными для нас будут два параметра: fps (он должен быть стабильным и не опускаться ниже 30 кадров в секунду) и speed (показывает, успеваем ли мы обрабатывать видео на лету). Для realtime параметр speed должен быть больше 1.00x. 

Проседания этих двух параметров приводят к выпадению кадров, артефактам, проблемам кодировки и другим повреждениям картинки, которые не хотелось бы видеть на записях с камер видеонаблюдения. 

Проверяем энкодинг на голом CPU

Запуск одной копии FFmpeg дает нам такую начальную картину:

 

Загрузка по ядрам процессора в среднем на уровне 18–20%, а вывод FFmpeg показывает следующее:

frame=196 fps=87 q=-1.0 Lsize=2685kB time=00:00:06.43 bitrate=3419.0kbits/s speed=2.84x

Запас есть, и можно попробовать сразу три потока:

frame=310 fps=54 q=29.0 size=4608kB time=00:00:07.63 bitrate=4945.3kbits/s speed=1.33x

Четыре потока выбирают почти все мощности CPU и «отъедают» 13 ГБ оперативной памяти.

При этом вывод FFmpeg показывает, что резервы не исчерпаны:

frame=332 fps=49 q=29.0 size=3072kB time=00:00:08.36 bitrate=3007.9kbits/s speed=1.23x

Увеличиваем количество потоков до пяти. Процессор держится на пределе, местами начинаются просадки скорости кадров и битрейта на 5–10%:

frame=491 fps=37 q=29.0 size=4864kB time=00:00:13.66 bitrate=2915.6kbits/s speed=1.03x

Запуск шести потоков показывает, что предел достигнут. Мы все больше и больше отстаем от реального времени и начинаем пропускать кадры:

frame=140 fps=23 q=29.0 size=1024kB time=00:00:01.96 bitrate=2954.4kbits/s speed=0.446x

Включаем мощности GPU

Запускаем один поток FFmpeg с энкодингом через h264_nvenc. Убеждаемся через вывод nvidia-smi, что у нас задействована именно видеокарта:

Поскольку вывод достаточно громоздкий, мы будем отслеживать параметры GPU с помощью следующей команды:

nvidia-smi dmon -s pucm

Расшифруем обозначения: 

  • pwr — потребляемая видеокартой мощность в ваттах;

  • gtemp — температура видеоядра (в градусах Цельсия);

  • sm — SM, mem — память, enc — энкодер, dec — декодер (утилизация их ресурсов указана в процентах);  

  • mclk — текущая частота памяти (в МГц), pclk — текущая частота процессора (в МГц); 

  • fb — использование кадрового буфера (в Мб).

gpu

pwr

gtemp

mtemp

sm

mem

enc

dec

mclk

pclk

fb

bar1

Idx

W

C

C

%

%

%

%

MHz

MHz

MB

MB

0

35

48

1

0

6

0

6500

1560

213

5

Нас в этом выводе будут интересовать значения загрузки энкодеров GPU и утилизации видеопамяти.

Вывод FFmpeg дает следующие результаты:

frame=192 fps=96 q=23.0 Lsize=1575kB time=00:00:06.36 bitrate=2027.1kbits/s speed=3.17x

Запускаем сразу пять потоков. Как видно из вывода htop, в случае энкодинга на GPU загрузка процессора минимальна, а большая часть работы ложится именно на видеокарту. Дисковая подсистема также загружена гораздо меньше.

gpu

pwr

gtemp

mtemp

sm

mem

enc

dec

mclk

pclk

fb

bar1

Idx

W

C

C

%

%

%

%

MHz

MHz

MB

MB

0

36

48

8

2

40

0

6500

1560

1035

14

Загрузка блоков энкодинга увеличилась до 40%, память мы заняли почти на гигабайт, но видеокарта по факту загружена не сильно. Вывод FFmpeg подтверждает это, показывая, что у нас есть ресурсы для увеличения количества потоков минимум в 2 раза: 

frame=239 fps=67 q=36.0 Lsize=2063kB time=00:00:07.93 bitrate=2130.3kbits/s speed=2.22x

Ставим десять потоков. Утилизация CPU на уровне 15–20%.

Параметры видеокарты:

gpu

pwr

gtemp

mtemp

sm

mem

enc

dec

mclk

pclk

fb

bar1

Idx

W

C

C

%

%

%

%

MHz

MHz

MB

MB

0

55

48

14

4

61

0

6500

1920

2064

24

Потребление электроэнергии возросло, видеокарта вынуждена была разогнать частоту видеоядра, но мощности энкодинга и видеопамять позволяют увеличивать нагрузку. Проверяем вывод FFmpeg, чтобы в этом убедиться:

frame=1401 fps=36 q=29.0 Lsize=12085kB time=00:00:46.66 bitrate=2121.5kbits/s speed=1.2x

Пробуем добавить еще четыре потока и получаем загрузку блоков энкодинга в 100%. 

gpu

pwr

gtemp

mtemp

sm

mem

enc

dec

mclk

pclk

fb

bar1

Idx

W

C

C

%

%

%

%

MHz

MHz

MB

MB

0

68

59

18

7

100

0

6500

1920

2886

33

Вывод FFmpeg подтверждает, что мы достигли предела. Утилизация CPU при этом все еще не превышает 20%.

frame=668 fps=31 q=26.0 Lsize=5968kB time=00:00:22.23 bitrate=2199.0kbits/s speed=1.04x

Контрольные 15 потоков показывают, что GPU начинает сдавать, так как блоки энкодинга работают с перегрузкой, а также наблюдается рост температуры и потребляемой мощности.

gpu

pwr

gtemp

mtemp

sm

mem

enc

dec

mclk

pclk

fb

bar1

Idx

W

C

C

%

%

%

%

MHz

MHz

MB

MB

0

70

63

18

7

100

0

6500

1920

3092

35

FFmpeg также подтверждает, что видеокарте становится тяжеловато. Частота обработки и пропуск кадров уже не внушают оптимизма:

frame=310 fps=28 q=29.0 size=2560kB time=00:00:10.23 bitrate=2049.4kbits/s speed=0.939x

CPU vs GPU

Подытожим: применение GPU в такой конфигурации можно назвать оправданным, поскольку максимальное количество обрабатываемых видеокартой потоков в 3 раза превышает возможности далеко не самых слабых процессоров (особенно без поддержки технологий аппаратного кодирования). С другой стороны, мы используем только минимальную часть возможностей видеоадаптера. Поскольку остальные его блоки и видеопамять не сильно нагружены, ресурсы дорогостоящего устройства утилизируются неэффективно.

Искушенные читатели могут заметить, что мы не проверили работу в режимах 2K/4K, не использовали возможности современных кодеков (наподобие h265 и VP8/9), а также установили в тестовый стенд видеоадаптер на архитектуре предыдущего поколения. Тот же A5000 должен показать лучший результат, но его работу мы проверим в следующей статье, а потом будем препарировать Intel Quick Sync.

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

Комментарии (11)


  1. redneko
    07.04.2022 23:10
    +5

    Хотелось бы еще увидеть сравнение метрик компрессированного видео (PSNR/SSIM) в зависимости от того, чем производилось кодирование. По опыту использовать аппаратное ускорение оправданно для live-потоков ввиду его скорости. Для VoD лучше подходит CPU ввиду того, что торопиться некуда и есть время для принятия кодером более оптимальных стратегий сжатия, влияющих существенным образом на качество картинки. К сожалению пока все общедоступные механизмы ускорения до сих уступают CPU по визуальному восприятию.


    1. Shannon
      08.04.2022 03:15

      Видел такое мнение про аппаратное ускорение, оно да, качеством заметно хуже при равном битрейте, но можно битрейт выставить повыше и в итоге 1ТБ видео файлов можно пережать за адекватное время, чем пытаться это делать на CPU.

      Это как кодек SVT-AV1, он сильно ускоряет кодирование в av1, но битрейт выше придется ставить.


      1. redneko
        08.04.2022 08:46
        +2

        Хорошо, когда битрейт можно повыше выставить, перекодируя свою личную коллекцию видеоматериалов.

        Нюансы начинаются там, где нужно с приемлемым качеством затранскодить какой-нибудь спортивный Live HD телеканал так, чтобы он еще пролез у ADSL-абонента (да-да, такие еще есть). И тут в игру вступают взаимоисключающие вещи: потолок битрейта 6Mbps CBR (из которых еще может быть две аудиодорожки в MPEG1L2@128kbps и чуть стаффинга), кодек H.264 (не все STB еще умеют в H.265, не говоря о AV1), и чтобы это выглядело хоть как-то прилично, а не игрой квадратных муравьёв в футбол.


      1. justmara
        09.04.2022 11:19

        да здесь же прям вывод

        на cpu: bitrate=3007.9kbits/s
        на gpu: bitrate=2027.1kbits/s
        учитывая, что хардварный кодек даже на сравнимых q даёт обычно гораздо более худшее качество, то при на треть меньшем битрейте выхлоп тут можно даже не сравнивать


  1. screwer
    08.04.2022 00:05
    +4

    Интересно в деньгах померять. Сколько потоков вытянут зионы 2678, стоимостью в три копейки.


    1. kasyachitche
      08.04.2022 09:05

      Согласен. Самые интересные метрики это стоимость обработки одного потока на конкретном железе (руб/поток) и потребляемая мощность на поток (Вт/поток).


    1. ULP
      08.04.2022 19:09

      старые Xeon не очень вытянут, там нет видеоядра где происходит вся магия и они тормозные отнсительно современных камней и много потребляют электричества, 2-3 потока и все.

      На современных померять можно просто, по калькулятору на https://hostkey.ru/gpu-dedicated-servers/ :

      машина с A4000 самая простая - 22000р, 12 потоков - 1800р на поток в месяц.

      машина с A5000 самая простая - 31000р, 14 потоков - 2214р/поток

      сервер на i9-9900K самый простой с QuickSync (QSV) - 5000-6000р, 11 потоков, 450р на поток. Сервера для такого надо собирать на матерях без удаленного управления, что мы умеем.


  1. edo1h
    08.04.2022 08:40

    а почему в заголовке сервера? у intel на xeon scalable же тоже нет видеокодирования


    1. ULP
      08.04.2022 19:12

      1. edo1h
        08.04.2022 23:13

        ну как много. xeon w официально считаются процессорами для рабочих станций.
        остаётся один xeon e, который по сути является небольшим тюнингом десктопного процессора: двухканальный контроллер памяти, относительно небольшое число ядер, отсутствие поддержки многосокетных конфигураций,…


        1. ULP
          08.04.2022 23:36

          Думаю математика будет 4 современных ядра процессора на HD поток если без графического ядра. Машина на 20 ядер за тысячи 3 евро потянет 5 потоков, а простой и не совсем свежий i9-9900k за 600 евро со всем вместе и QSV потянет 14 потоков. Мы это рассмотрим в дальнейших публикациях.