用于Linux 2的Windows子系统上的CUDA

2020-06-19 02:40:52

为了响应大众的需求,微软在2020年5月的构建大会上宣布了Windows Subsystem for Linux2(WSL2)的一个新功能-GPU加速。此功能为许多计算应用程序、专业工具和工作负载打开了大门,这些应用程序、专业工具和工作负载目前只能在Linux上使用,但现在可以按原样在Windows上运行,并受益于GPU加速。

最重要的是,NVIDIA CUDA加速现已进入WSL。在这篇文章中,我们将在WSL2的公共预览版中讨论您对CUDA的期待。

WSL是Windows10的一项功能,它使您能够直接在Windows上运行原生Linux命令行工具,而不需要复杂的双引导环境。在内部,WSL是与Microsoft Windows操作系统紧密集成的集装箱化环境。这使得它可以与传统的Windows桌面和现代商店应用程序一起运行Linux应用程序。

WSL主要是供开发人员使用的工具。如果您在Linux容器内处理计算工作负载,则可以使用您熟悉的本地Linux工具在Windows PC上本地开发和测试工作负载。通常,这些应用程序需要大量黑客攻击、第三方框架和库才能在Windows系统上运行。WSL2改变了这一切,它为Windows世界带来了全面的Linux内核支持。

借助WSL 2和GPU准虚拟化(GPU-PV)技术,微软允许您运行针对GPU硬件的计算工作负载,从而为Windows上的Linux支持再添一笔。在这篇文章的后面,我们将更详细地介绍WSL2以及GPU是如何添加到那里的。

有关更多信息,请参阅DirectX即将进入Windows Subsystem for Linux和GitHub中的wsl2-linux-Kernel/driver/gpu目录。

要利用WSL 2中的GPU,目标系统必须安装支持Microsoft WDDM模型的GPU驱动程序。这些驱动程序由NVIDIA等GPU硬件供应商提供。

CUDA使您能够对NVIDIA GPU进行编程。几十年来,Windows图形中的WDDM模型一直支持它。新的Microsoft WSL 2容器提供GPU加速,CUDA可以利用它在WSL中运行CUDA工作负载。有关详细信息,请参阅《CUDA on WSL用户指南》。

针对WDDM 2.9型号的NVIDIA显示驱动程序包括对WSL中的CUDA的支持。您只需在Windows主机上安装驱动程序。WSL(libcuda.so)中的CUDA用户模式驱动程序会自动映射到容器内部,并添加到那里的加载器搜索路径中。

NVIDIA驱动程序开发团队向CUDA驱动程序添加了对WDDM模型和GPU-PV的支持,以便能够在Windows上的Linux上运行它。它仍然是一个预览驱动程序,在Windows10的WSL中对GPU的官方支持发布之前不会发布。有关该版本的更多信息,请参阅CUDA WSL 2下载。

图2显示了如何将CUDA驱动程序插入Linux来宾系统中的新WDDM模型的简单示意图。

如果你是一名开发者,从微软Windows Insider程序的Fast Ring(20149版或更高版本)在最新的视窗版本上安装了wsl发行版,并将容器设置为在wsl 2模式下运行,如果你是PC中NVIDIA GPU的灵感所有者,你可以在wsl 2中尝试驱动程序并运行你的工作负载。你所要做的就是在你的视窗主机操作系统上安装驱动程序,然后打开wsl容器。Cuda将在那里使用CUDA应用程序,而不需要任何额外的努力。图3显示了在WSL2容器中运行CUDA TensorFlow工作负载的屏幕截图。

WSL中的GPU为目前仅在本地Linux环境中运行的各种CUDA计算应用程序打开了大门。

NVIDIA仍在积极致力于这一项目,并进行调整。其中,我们正在致力于将过去特定于Linux的API引入WDDM层,以便越来越多的应用程序可以开箱即用地使用WSL。

另一个关注点是性能。如前所述,WSL2GPU支持大量利用GPU-PV,这可以在没有任何流水线的情况下影响小型GPU工作负载。现在,我们正在尽可能多地减少这种开销。

NVML不包括在最初的驱动程序包中,对此有一些担忧。为了解决这个问题,我们计划将NVML和其他库一起引入WSL。

我们首先启动了核心CUDA驱动程序,让您可以在此早期预览版中尝试大多数现有工作负载。我们意识到,一些容器和应用程序甚至在加载CUDA之前就利用NVML来查询GPU信息。这就是为什么我们将NVML放在WSL上作为我们的首要任务。敬请关注有关此主题的更多更新。

除了DirectX和CUDA支持外,NVIDIA还在WSL 2中增加了对NVIDIA Container Toolkit(以前称为nvidia-docker2)的支持。数据科学家准备在本地硬件上Linux下运行或在云中执行的集装箱化GPU工作负载现在可以在Windows PC上的WSL 2中按原样运行。

不需要特定的WSL包。NVIDIA运行时库(libnvidia-tainer)可以动态检测libdxcore,并在具有GPU加速的WSL 2环境中运行时使用它。这在安装Docker和NVIDIA Container Toolkit包后自动发生,就像在Linux上一样,允许GPU加速的容器开箱即用。

我们建议您获取最新版本的Docker工具(19.03或更高版本),以利用添加的对--gpu选项的支持。要启用WSL2支持,请遵循适用于您的Linux发行版的GitHub Repo上的自述文件步骤,并安装可用的最新版本。

那么它是如何工作的呢?所有特定于WSL2的工作都由libnvidia-tainer库处理。该库现在能够在运行时检测libdxcore.so的存在,并使用它检测向此接口公开的所有GPU。

如果需要在容器中使用这些GPU,则使用libdxcore.so查询驱动程序存储的位置,该文件夹包含Windows主机和WSL 2的所有驱动程序库。由libnvidia-tainer.so负责设置容器,以便正确映射驱动程序存储,并为WSL2GPU支持的核心库执行设置,如图4所示。

此外,这与在WSL外部使用的逻辑不同。这是由libnvidia-tainer.so完全抽象的,应该对最终用户尽可能透明。此早期版本的限制之一是在多GPU环境中缺少GPU选择:所有GPU在容器中始终可见。

下面是您可以在WSL容器中运行的内容:您目前熟悉的任何NVIDIA Linux容器。NVIDIA支持专业人士使用的大多数现有Linux工具和工作流程。从NVIDIA NGC下载喜欢的容器工作负载,并尝试一下。

在下一节中,我们将介绍如何在由NVIDIA GPU加速的工作负载下,在WSL 2中运行TensorFlow和n-body容器。

安装NVIDIA容器工具包。从nvidia-docker2v2.3和底层运行时库libnvidia-tainer1.2.0-rc.1开始提供WSL2支持。

设置稳定的实验存储库和GPG密钥。为支持WSL2而对运行时所做的更改可以在实验存储库中找到。

user@PCName:/mnt/c$Distribution=$(.。/etc/os-release;ECHO$ID$VERSION_ID)USER@PC名称:/mnt/c$CURL-s-L https://nvidia.github.io/nvidia-docker/gpgkey|sudo APT-KEY ADD-USER@PC名称:/mnt/c$CURL-s-L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list|SUDO TEE/etc/apt/sources.list.d/nvidia-docker.listuser@PCName:/mnt/c$CURL-s-L https://nvidia.github.io/libnvidia-container/experimental。/$distribution/libnvidia-container-experimental.list|sudo tee/etc/apt/sources.list.d/libnvidia-container-experimental.list。

打开WSL容器并在那里启动Docker守护进程。您应该会看到dockerd服务输出。

在另一个WSL容器窗口中,下载并启动N-Body模拟容器。确保用户有足够的权限下载容器。您可能需要在sudo中运行以下命令。GPU在输出中突出显示。

下载TensorFlow Docker映像。为了避免Docker连接问题,该命令在sudo中运行。

将第15课的稍作修改的版本-使用TensorFlow教程中的GPU保存在主机的驱动器C上,默认情况下,该驱动器在WSL 2容器中映射为/mnt/c。

user@PCName:/mnt/c$vi./matmul.pyimport sysimport number py as npimport TensorFlow as tffrom datetime import datetimedevice_name=sys.argv[1]#从cmd行选择设备。选项:GPU或cpushape=(int(sys.argv[2]),int(sys.argv[2])),如果DEVICE_NAME==";GPU";:DEVICE_NAME=";/GPU:0";ELSE:DEVICE_NAME=";/CPU:0";带有tf.device(设备名)的tf.compat.v1.Disable_Eager_Execution():tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(log_device_placement=True))_Matrix=tf.随机性.uniform(Shape=Shape,minval=0,maxval=1)dot_operation=tf.matmul(随机矩阵,tf.transspose(随机矩阵))SUM_OPERATION=tf.duce_SUM(点操作)startTime=datetime.now(),会话为tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(log_device_placement=True)):Result=session.run(SUM_OPERATION)。形状:";,形状,";设备:";,设备名称)打印(";花费的时间:";,datetime.now()-startTime)。

在GPU和CPU上运行此脚本(从挂载的驱动器C启动)的结果如下所示。为简单起见,减少了输出。

在较早的计算方案中,当在WSL 2容器中使用GPU时,会有显著的加速。

这里有另一个由GPU加速的演示:Jupyter笔记本教程。启动容器时,您应该看到打印了指向笔记本服务器的链接。

现在您应该能够在Jupyter笔记本上运行演示示例了。连接到笔记本时,请小心使用Microsoft Edge浏览器中的localhost,而不是127.0.0.1。

要查看由Windows PC的GPU加速的工作,请导航到Cell菜单,选择Run All,然后检查Jupyter笔记本的WSL 2容器中的日志。

此演示和此容器中的其他一些演示强调了小提交的虚拟化层当前的开销问题,前面也提到过。与这些玩具模型相关联的提交导致GPU运行时间比同步开销本身更短。在WSL 2上的这些非常小的模型情况下,CPU时间可能比GPU时间更好。这一点目前正在优化,应该仅限于较小的非流水线工作负载。

为了理解如何将GPU添加到WSL2中,我们现在讨论什么是Windows上的Linux,以及硬件是如何向容器公开的。

微软在2016年的Build大会上推出了WSL。它很快获得了发展势头,并成为Linux开发人员中的热门工具,这些开发人员希望与Linux开发工具和目标工作负载一起运行Windows应用程序(如Office)。

WSL 1允许运行未经修改的Linux二进制文件。但是,它仍然使用Linux内核模拟层,该层是作为NT内核中的一个子系统实现的。该子系统通过将来自Linux应用程序的调用转发到相应的Windows 10功能来处理这些调用。

WSL1是一个有用的工具,但是它并不兼容所有的Linux应用程序,因为它可能需要模拟所有的Linux系统调用。通常,文件系统访问速度也很慢,这会导致某些实际应用程序的性能无法接受。

考虑到这一点,微软决定走另一条路,并推出了WSL的新版本WSL2。WSL 2容器在虚拟化环境中运行完整的Linux发行版,同时仍然利用Windows10新容器系统的全部优势。

虽然WSL2使用了Windows10的Hyper-V服务,但它仍然不是传统的虚拟机,而是一个轻量级的实用虚拟机。该实用程序管理虚拟地址支持的内存,允许WSL2容器从主机Windows系统动态分配内存。

WSL2的一些主要目标是提高文件系统性能并支持完全系统调用兼容性。它还具有更好的整体Windows主机系统集成。它允许从Windows shell到在容器内运行的Linux系统的快捷方式,以及对自动挂载到容器文件系统的选定目录中的主机文件系统的访问。

WSL 2作为Windows Insider计划的一项预览功能启用,并已作为最新的Windows 10更新(2004版)发布。

在最新的Windows版本中,从网络堆栈到底层存储VHD,对WSL2容器进行了更多改进。描述所有细节都超出了这篇文章的范围。有关WSL2容器的一些有趣和激动人心的新特性的更多信息,请参见比较WSL2和WSL1。

WSL2中的Linux内核是由微软根据kernel.org上提供的源代码,从最新的稳定分支构建的。该内核专门针对WSL2进行了调优,针对大小和性能进行了优化,以便在Windows上提供Linux体验。内核由Windows Update提供服务,这意味着您无需自己管理即可获得最新的安全修复和内核改进。

微软在WSL中支持几个Linux发行版。遵循开放源码社区的规则,WSL2内核源代码经过必要的修改以允许与Windows10主机进行系统集成是公开的,并可在WSL2-Linux-Kernel GitHub repo上获得。

微软开发人员正在通过GPU-PV技术将真正的GPU硬件支持带到WSL 2容器中,其中操作系统图形内核(Dxgkrnl)将运行在来宾VM内的用户模式组件的调用编组到驻留在主机上的内核模式驱动程序。

微软在几个Windows版本之前,在独立硬件供应商(IHV)的帮助下开发了这项技术,将其作为其WDDM图形驱动程序模型的一项功能。NVIDIA图形驱动程序从Windows操作系统的Windows Insider Program中功能预览的早期开始就支持GPU-PV。当前支持的所有NVIDIA GPU都可以暴露给在Hyper-V VM来宾内部运行的Windows操作系统。

为了让WSL2能够利用GPU-PV的强大功能,微软必须在Linux客户系统中实现其图形框架的基础:使用GPU-PV协议的WDDM模型。新的微软驱动程序支持Linux上的WDDM模型,称为dxgkrnl。它也可以作为源代码项目在WSL2-Linux-Kernel GitHub资源库中获得。

dxgkrnl驱动程序有望为WDDM2.9版本的WSL2容器带来对GPU加速的支持。微软解释说,dxgkrnl是一个基于GPU-PV协议的Linux GPU驱动程序,与其同名的Windows驱动程序没有任何其他共同之处。

目前,您可以下载NVIDIA WDDM 2.9驱动程序的预览版。在接下来的几个月里,将从Windows Update的WIP版本分发NVIDIA WDDM 2.9驱动程序,这使得无需手动下载和安装该驱动程序。

dxgkrnl驱动程序在Linux来宾操作系统中将新的/dev/dxg设备公开给用户模式。已经在Windows上提供的D3DKMT内核服务层也正在作为dxcore库的一部分移植到Linux。它使用一组私有IOCTL调用与dxgkrnl通信。

来宾Linux版本的dxgkrnl使用多个VM总线通道连接到Windows主机上的dxg内核。主机上的dxg内核处理Linux进程提交的方式与处理运行在WDDM模型中的本地Windows应用程序提交的进程相同。它将它们发送到KMD(一个特定于IHV的内核模式驱动程序),KMD准备它们并将它们提交给硬件GPU。图10显示了这种通信信道的简化图。

NVIDIA驱动程序在许多版本的Windows来宾中都支持Windows 10 GPU-PV。NVIDIA GPU可用于加速使用Microsoft虚拟化层的所有最终用户Windows 10应用程序中的计算和图形,并使用GPU-PV功能添加vGPU:

图11显示了在NVIDIA GeForce GTX 1070 GPU上的Windows沙盒容器中运行示例DirectX应用程序的示例。

为了在WSL中启用图形,Windows图形团队还将一个用户模式组件移植到Linux:dxcore。

dxcore库提供API函数来枚举系统中符合WDDM的图形适配器。它旨在作为Windows和Linux中的DXGI适配器枚举的跨平台、低级替代。它还通过D3DKMT层API抽象了对dxgkrnl服务(Linux上的IOCTL和Windows上的GDI调用)的访问,CUDA和其他依赖于WSL中的WDDM模型支持的用户模式组件使用D3DKMT层API。

根据微软的说法,dxcore(libdxcore.so)库将在Windows和Linux上都可用。NVIDIA计划在驱动程序中增加对DirectX 12和CUDA API的支持,目标是WDDM 2.9型号的新WSL功能。这两个API库都将链接到dxcore,以便它们可以指示dxg内核将它们的请求编组到主机上的KMD。

如果您想要在舒适的Linux环境中使用您的Windows PC进行真正的ML和AI开发,WSL中对CUDA的支持将为您带来一个令人兴奋的机会。在WSL,Docker CUDA Containers已被证明是数据科学家中最受欢迎的计算环境之一。

加入Microsoft Windows Insider计划以访问启用了GPU加速的WSL 2预览。

下载并安装最新的NVIDIA驱动程序,然后尝试在WSL 2中运行CUDA容器化工作负载。

了解有关WSL上的CUDA的更多信息,并在我们的社区论坛上分享您的评论、反馈和想法。