Skoči na vsebino

Uporaba grafičnih procesnih enot

Grafična procesna enota (angl. graphics processing unit) ali GPE je poseben procesor, v osnovi namenjen izrisovanju slike na zaslon. Med drugim so GPE optimizirane za hitro računanje z vektorji in matrikami, ki je pogosta operacija pri delu z grafiko. Čeprav GPE niso primerne za reševanje splošnih problemov, se izkaže, da so operacije, ki jih znajo GPE zelo hitro izvesti uporabne tudi v drugih domenah, na primer strojnem učenju in rudarjenju kriptovalut. Prav tako imajo sodobne GPE vgrajeno podporo za delo z nekaterimi vrstami videoposnetkov. Poglejmo, kako lahko uporabimo GPE za hitrejšo pretvorbo videoposnetka v drug zapis.

Programi, kot je ffmpeg, lahko GPE različnih proizvajalcev uporabljajo preko standardnih vmesnikov. Najpogosteje se uporabljata OpenCL in CUDA. Slednji je namenjen samo za grafične procesne enote podjetja Nvidia. Ti so nameščeni tudi v gruči ARNES.

Pripravljanje vsebnika

Program ffmpeg privzeto ne podpira GPE, temveč ga moramo prevesti s posebnimi nastavitvami. Tu bomo uporabili obstoječi vsebnik za Docker, ki že vsebuje ustrezno različico programa ffmpeg. V vsebnik za Apptainer ga pretvorimo z ukazom

$ apptainer pull docker://jrottenberg/ffmpeg:7-nvidia
apptainer pull docker://jrottenberg/ffmpeg:7-nvidia

V trenutnem imeniku smo ustvarili vsebnik ffmpeg_7-nvidia.sif. Ta vsebnik uporabimo kot običajno z ukazom apptainer exec:

$ apptainer exec ffmpeg_7-nvidia.sif ffmpeg -version
fmpeg version 7.0 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 13 (Ubuntu 13.2.0-23ubuntu4)
configuration: --disable-debug --disable-doc --disable-ffplay --enable-cuda --enable-cuvid ...
apptainer exec ffmpeg_7.nvidia.sif ffmpeg -version

Zgronji ukaz vidimo nam izpiše nastavitve, ki vklopijo podporo za GPE (CUDA) in sorodne tehnologije. Tehnologije, ki jih podpira neka različica ffmpeg, lahko preverimo z argumentom -hwaccels:

$ apptainer exec ffmpeg_7-nvidia.sif ffmpeg -hwaccels
ffmpeg version 7.0 Copyright (c) 2000-2024 the FFmpeg developers
...
Hardware acceleration methods:
vdpau
cuda
vaapi
drm
apptainer exec ffmpeg_7-nvidia.sif ffmpeg -hwaccels

Obdelava videoposnetka na grafični procesni enoti

Najprej moramo nastaviti ustrezno okoljsko spremenljivko, s katero definiramo vrste operacij, ki jih lahko izvajamo na grafični procesni enoti.

$ export NVIDIA_DRIVER_CAPABILITIES=compute,utility,video 
export NVIDIA_DRIVER_CAPABILITIES=compute,utility,video 

Preizkusili bomo knjižnico cuda, ki med drugim zna kodirati zapis H.264 na grafični procesni enoti. Če želimo v poslih uporabljati grafične procesne enote, moramo podati ustrezne argumente:

$ srun --partition=gpu --gpus=1 apptainer exec --nv ffmpeg_7-nvidia.sif ffmpeg \
-hwaccel cuda -hwaccel_output_format cuda \
-y -i llama.mp4 -codec:a copy -filter:v scale_npp=640:360 \
-codec:v h264_nvenc gpe-llama.mp4
 srun --partition=gpu --gpus=1 apptainer exec --nv ffmpeg_7-nvidia.sif ffmpeg -hwaccel cuda -hwaccel_output_format cuda -y -i llama.mp4 -codec:a copy -filter:v scale_npp=640:360  -codec:v h264_nvenc gpe-llama.mp4

Najprej z argumentom --gpus=1 od Slurma zahtevamo vozlišče z eno grafično procesno enoto. Na dodeljenem vozlišču zaženemo vsebnik s apptainer exec --nv. S stikalom --nv dovolimo, da programi v vsebniku lahko dostopajo do grafične procesne enote. Končno zahtevamo, da program ffmpeg dejansko uporabi grafično pospeševanje za kodiranje videa. Ker ffmpeg ne zna avtomatsko zaznati prisotnosti grafične procesne enote in zagnati ustreznih funkcij, zahteve podamo sami:

  • s -hwaccel cuda -hwaccel_output_format cuda naložimo ustrezne knjižnice,
  • s scale_npp povemo, naj namesto običajnega filtra scale uporablja filter, pripravljen za grafične procesne enote (npp - Nvidia performance primitives),
  • s -codec:v h264_nvenc pa izberemo kodirni algoritem H.264, pripravljen za grafične procesne enote.

Ostale nastavitve so enake kot prej. V vseh dosedanjih klicih programa ffmpeg nismo navajali kodirnega algoritma, saj je nastavitev -codec: v h264 privzeta in jo zato lahko izpustimo.

Če je šlo vse po sreči, poteka kodiranje zdaj precej hitreje:

frame=19037 fps=273 q=14.0 Lsize=  162042kB time=00:10:34.55 bitrate=2091.9kbits/s speed= 9.1x

Za razliko od prejšnjih pristopov te pohitritve nismo dosegli z vzporedno obdelavo na nivoju datotek, temveč smo za samo kodiranje videoposnetka uporabili strojno opremo, ki zna zahtevane operacije izvajati veliko hitreje. Tudi tu gre v resnici za vzporedno računanje, a na precej nižjem nivoju, saj lahko GPE pri kodiranju vsake posamezne sličice izvaja več sto ali tisoč vzporednih operacij.

Vaja

Na povezavi najdete naloge za utrditev znanja o postopku paralelizacije obdelave videoposnetkov na gruči.