WSL中的GPU原理总结

自wsl(Windows Subsystem on Linux)发布以来,许多性能已经得到了长足的进步。经过多年的发展,该项目从一个玩具项目发展成现在可以真正用于生产环境的项目,给需要使用Linux环境但是又不想脱离Windows便利生态的开发者们来说带来了福音。
wsl的图形性能也受到许多人的关注,特别是自微软2020build大会官方发布支持图形界面的wslg之后,wsl的图形性能发展进入了快车道。本文主要结合微软和英伟达提供的资料简要总结了一下wsl中调用GPU的原理以及使用GPU进行3D渲染加速和CUDA编程可能遇到的问题。

原理

关于wsl是如何调用GPU加速的主要参考了这篇微软推出的博客。这篇博客里把大概的原理讲清楚了,简单来说就是hyperv虚拟机虚拟了一个/dev/dxg硬件,这个硬件通过WDDM(Windows Display Driver Model)(版本不低于2.9)共享了Windows端的显卡,然后在这个虚拟出的硬件上建立了一个Direct 3D的API实现了在Linux上使用Direct 3D(真的会有人在Linux上用这个吗。。。)。然后通过修改Mesa(OpenGL的开源实现)来实现了对OpenGL的支持(暂时还不支持vulkan),以及让Nvidia单独推出了一个版本的CUDA调用D3D的API来实现通用计算。这样,显卡虚拟化最重要的图形流水线和计算流水线都得到了支持。其实下面这几张从官方博客中截取出来的图能够更好的说明这个调用关系。

可以看出这套方案还是很精妙的,是目前我已知的唯一不使用显卡直通,不适用英伟达专业卡的虚拟化接口等技术的虚拟化方案了。显卡直通会让宿主机无法使用显卡,而后者仅供专业卡使用。都有一些缺陷。而vmware等虽然能实现图形流水线从而进行3D加速,但是无法使用CUDA并行加速计算,因此难以用来进行科学计算等任务。这套方案的精妙之处是巧妙的使用了windows的显示驱动模型实现共享,以及让Nvidia单独推出了wsl版本的CUDA来支持计算流水线。了解原理后对出现故障的修复很有帮助。

CUDA使用与性能分析

CUDA的使用还是比较简单,按照原理的描述,首先需要找一个支持WDDM2.9以上的显卡驱动(官网下载的最新版就支持),然后去Nvidia的CUDA下载页面下载wsl专用的CUDA工具包。安装完成后分别在wsl和Windows上执行nvidia-smi命令,应该可以发现驱动版本是完全一致的。之后就一切按照正常的Linux环境配置就可以开启炼丹之旅了。由于wsl对内存进行了虚拟化,因此显存不够时可以使用内存作为虚拟显存使用,这么虽然慢一点,但是可以缓解小显存无法开大batch size的情况。
从原理上看增加了这么多调用确实会降低一些性能。这篇来自Nvidia的技术报告详细的测试了性能的损失。从这张图中可以看到随着batch_size的增加,wsl与原生linux之间的性能差距在逐渐缩小。这是由于额外开销只发生在调用GPU的阶段。所以尽可能的减少对GPU的调用,并让GPU充分忙碌,提升性能,这对所有的cuda编程都有效。(毕竟就算是原生系统,创建cuda核函数,复制内存等也需要时间)。总的来说,确实有很大的性能下降,但是也还在可接受范围内,此外nvidia在报告中也提到他们在改善性能,比最初发布的版本已经快很多了。

3D加速

与上一段讲的通用计算不同,本章讲的图形渲染加速又是另一个故事了。这里主要介绍OpenGL的配置,目前来看想使用GPU加速直接下载最新版本的Mesa即可。但可能需要设置一下后端的名字。使用MESA_D3D12_DEFAULT_ADAPTER_NAME变量来指定。具体可以参考这篇文档
安装完成后可以输入glxinfo -B命令来查看,如果输出有显卡的名字那么基本安装成功了,如果还是输出LLVM等字样那么说明还是使用CPU在计算。也可以通过glxgears程序来判断,如果在任务管理器中发现GPU占用上升,且CPU负载不高那么证明加速成功。当然显示情况也跟RDP有关,这里放一张窗口显示的框架。

最后说一个任务管理器的奇怪特性,如果在设置中关闭了GPU加速调度选项,那么无法看到wsl的3D渲染对gpu的占用情况,但是任务管理器此时可以看到CUDA的占用,如果开启,可以看到wsl的3D渲染占用gpu了,但是CUDA的选项就消失了。

结语

本文大概总结了一下wslg的现状,详细内容建议阅读本文出现的几篇官方文档。总的来说wslg经过调教基本可以作为生产工具使用,但是还存在一些问题,比如各种lib需要手动安装,不支持vulkan,cuda效率不高等问题,相信只要微软不弃坑,这些问题都会逐渐得到解决。(至少比wsl1的技术路线好多了)


EOF