docker中如何应用GPU

问题描述

我们采用了Xvfb虚拟屏在容器环境下进行网页录屏操作,但是我们的网页应用到了3D效果,发现很卡。查看Puppeteer的打印信息,发现GPU加速是开启来了,可实际感受似乎没生效。因此需要寻找原因。

需要确定:

  • 是系统没装显示器的原因么?
  • 是Puppeteer的原因么?
  • 是Xvfb的原因么?
  • 是宿主机GPU的原因么?

这个文章描述,可能缺少依赖?

https://stackoverflow.com/questions/69351416/docker-webgl-headless-chrome-error-passthrough-is-not-supported-gl-is-disa

为什么headless模式无法使用GPU?

参考官方的回答:

https://bugs.chromium.org/p/chromium/issues/detail?id=706008#c5

To give an update, we’ve decided against implementing extension support in headless mode for now because supporting all the required features is rather complex.

https://bugs.chromium.org/p/chromium/issues/detail?id=765284#c19

我们用了Chrome插件,插件必须要求headless=false,就是这个玩意儿把我们卡住了。

如果我们不用Chrome插件的方式,用截屏的方式,应该就可以把GPU用起来了。

通过Xvfb在headless模式使用Chrome扩展

这个答案讲到了一种方式:

https://stackoverflow.com/questions/45372066/is-it-possible-to-run-google-chrome-in-headless-mode-with-extensions

  • Xvfb启动Chrome浏览器,播放网页(渲染是在这个进程?)
  • 通过chrome-remote-interface,给浏览器发送命令,执行诸如截屏之类的操作

这里有个PPT,也是类似的方式(还用到了FFmpeg),不过可惜这个是截屏,不是录屏,和Puppeteer类似:

https://docs.google.com/presentation/d/1b-HvxKmeFYE3qoNDJDHfbgVwEbi0QgmTvpH8w4CK5Tw/htmlpresent

受此启发,我们是不是也可以用FFmpeg录制的方式呢?

无头浏览器开启GPU+FFmpeg录制

通过Puppeteer-stream录制

https://juejin.cn/post/7005114794386653192

这个我看设置的是headless=true,试试?

github:https://github.com/Flam3rboy/puppeteer-stream#readme

什么是离屏渲染(off screen rendering)?

这个方案感觉可行

https://medium.com/@benjamin.botto/opengl-and-cuda-applications-in-docker-af0eece000f1#id_token=eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzgzNjExMzcsImF1ZCI6IjIxNjI5NjAzNTgzNC1rMWs2cWUwNjBzMnRwMmEyamFtNGxqZGNtczAwc3R0Zy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwOTg4ODE2Nzk5NzUyNDY2NzYzNCIsImVtYWlsIjoic3VwZXJ6aG91MjAwN0BnbWFpbC5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiMjE2Mjk2MDM1ODM0LWsxazZxZTA2MHMydHAyYTJqYW00bGpkY21zMDBzdHRnLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkxlbyBaaG91IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdqMEcwRHdENEpVMWZVMUNWR19MTHBpRGd1dGFmbURZcjhBRklheD1zOTYtYyIsImdpdmVuX25hbWUiOiJMZW8iLCJmYW1pbHlfbmFtZSI6Ilpob3UiLCJpYXQiOjE2MzgzNjE0MzcsImV4cCI6MTYzODM2NTAzNywianRpIjoiOTM1YzU4MmJjYzBmNGNmYTY3MTgzYjFlYTE4ZjQwNTdlMWQxNmZhMiJ9.Yxlqkzhn-ag-GOdVfKmTW7j6saZBTDkfs4qXwHnTTWBLdXgE2JiBWlsT56ZJ2ga9cEc-Jchj3luL2fap7DIcvyGa1b6AHRidMCl2ixfeeD9r5b5-upJyH3qa9zkyifAX-hM_SthmbKDv8BaiNq6_eBNgWdc4_AqmkE72gme5yh9Drru6IjyA8Zq5Ee1AdZra44cfwM01TIqOs9xWtESJY5DccyzZ5F9rbUtcPMSlCFmgriuTTAiujGkZxDVojeg5hmpnIIPYWix4tjKoYQrWCv11Zy8WDCv6p3WXXs7BLRC9Egx_eGFa5RJWUGxTZdD9eAfRNtcLW7KiSiTwIgq7OQ

得依赖于宿主机,且需要安装各种驱动和依赖的库。

官方教程:

https://developer.nvidia.com/blog/gpu-containers-runtime/

这个方案更明确

https://www.cnyunwei.cc/archives/1865

1.物理机上已经完成GPU驱动安装,并且通过基本测试GPU设备可以正常调用;
2.容器的基础镜像需要选择NVIDIA提供的镜像,已经集成了相关软件和驱动;
3.容器中不做显示服务(xorg)监听,直接共享物理机显示服务和GPU硬件;
4.本文章物理机系统Centos7,根据之前文章安装好了GPU驱动。

方案

安装X Display

写JS测试下支不支持WebGL

测试是否开启了nvidia driver

怀疑是没安装驱动?

服务端渲染

Xvfb不支持GPU

参考这个回答:

https://stackoverflow.com/questions/60521682/does-using-xvfb-to-run-opengl-effects-version

Xvfb is an X server which whole purpose is to provide X11 services without having dedicated graphics hardware (i.e. a GPU). So it’s the exact opposite of what you want.

Either don’t use X11 at all and create a headless EGL OpenGL context: https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/

Or use the “regular” Xorg server on the GPU without a display and input devices attached (you actually might want to disable automatic input device attachment in the configuration).

Personally I’d go with headless EGL.

Xvfb是一个实现了X11显示服务协议的显示服务器。 不同于其他显示服务器,Xvfb在内存中执行所有的图形操作,

既然是内存中执行所有操作,那么就肯定用不起来GPU了吧?

Xvfb的替代方案

I see x11docker uses a special setup with Weston, Xwayland and xdotool instead of Xdummy or Xvfb to allow GPU access.

I don’t really know what that all means, but from what I’ve been reading it appears that’s the best way to do this and have GPU acceleration.

(精)借助宿主机执行

I’ve explore how to make GPU supported in docker container for 3D rendering. My settings are RTX 2070 and nvidia driver installed.

Basically you need a nvidia contianer runtime (see the N-body example here https://developer.nvidia.com/blog/gpu-containers-runtime )

open a virtual display X server like :1 (https://medium.com/@renaldaszioma/how-to-run-unity-rendering-on-amazon-cloud-or-without-monitor-699eed0ce963)

map the virtual display :1 into the container using command “docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=:1”

then using DISPLAY=:1 to start applications. This makes applications run on the X server outside of the container and utilize the GPU device on the host machine.

This article includes more implementation details.
https://medium.com/@benjamin.botto/opengl-and-cuda-applications-in-docker-af0eece000f1

另外个方案

https://medium.com/@benjamin.botto/opengl-and-cuda-applications-in-docker-af0eece000f1

【精】Xorg和Xwayland、xpra

我知乎上咨询了大泽Official这位用户:

您好,我看你的回答有涉及xvfb,请问下centos下使用xvfb,有没有什么办法可以将GPU利用起来呢?我们现在用Xvfb+Chromium在CentOS下录制网页,发现GPU是不生效的。

额,同样的问题我也遇到了。。。
我的解决方案是换用xorg
另外我目前就找到两款支持gpu的xserver:xwayland和xorg

另外xpra也支持GPU:https://github.com/Xpra-org/xpra

常见报错

  • andbox_linux.c(374):InitializeSandbox() called with multiple threads in process gpu-process

这个文章说是删掉缓存就可以了:

http://hongouru.blogspot.com/2018/11/solved-linux-google-chrome.html

这个文章提到设置驱动路径,但是这和我们的场景似乎有点不一样:

https://stackoverflow.com/questions/69037458/selenium-chromedriver-gives-initializesandbox-called-with-multiple-threads-in

参考资料

Switch from xvfb to allow for GPU Acceleration #13:

https://github.com/solarkennedy/wine-x11-novnc-docker/issues/13

xrandr是啥: