适用于Linux 2的Windows子系统上的CUDA
Announcing CUDA on Windows Subsystem for Linux 2
为了响应大众的需求,微软在2020年5月的构建会议上宣布了WindowsSubsystem for Linux2(WSL2)的一个新特性——GPU加速。这一特性为许多计算应用程序、专业工具和工作负载打开了大门,目前只有Linux才有,但现在可以在Windows上按原样运行,并从GPU加速中获益。
最重要的是,NVIDIA CUDA加速度现在来到了WSL。在这篇文章中,将讨论在WSL 2的公共预览中对CUDA的期望。
WSL是Windows 10的一个特性,使能够直接在Windows上运行本机Linux命令行工具,而不需要复杂的双引导环境。在内部,WSL是一个与Microsoft Windows操作系统紧密集成的容器化环境。这使得可以在传统的Windows桌面和现代商店应用程序的同时运行Linux应用程序。
WSL主要是开发人员的工具。如果正在Linux容器中处理计算工作负载,则可以使用熟悉的本地Linux工具在Windows PC上本地开发和测试工作负载。通常,这些应用程序需要大量的黑客、第三方框架和库才能在Windows系统上运行。所有这些都随WSL 2而改变,WSL 2为Windows世界带来了完整的Linux内核支持。
借助WSL 2和GPU半虚拟化(GPU-PV)技术,微软正在为Windows上的Linux支持添加另一个功能,允许运行针对GPU硬件的计算工作负载。在本文后面,将更详细地介绍WSL 2以及GPU是如何添加到其中的。
有关更多信息,请参见DirectX进入Windows 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工作负载。有关更多信息,请参阅《关于WSL的CUDA用户指南》。
在WSL中对CUDA的支持包含在针对WDDM 2.9模型的NVIDIA显示驱动程序中。只需要在Windows主机上安装驱动程序。WSL中的CUDA用户模式驱动程序(利布达)自动映射到容器内并添加到该容器的加载程序搜索路径中。
NVIDIA驱动程序开发团队为CUDA驱动程序添加了对WDDM模型和GPU-PV的支持,以便能够在Windows上的Linux上运行。仍然是一个预览驱动程序,在Windows 10中WSL的官方GPU支持发布之前不会发布。有关该版本的更多信息,请参阅CUDA WSL 2下载。
图2显示了如何将CUDA驱动程序插入Linux客户机中的新WDDM模型的简单图。
Figure 1. Stack image showing layers involved while running Linux AI frameworks in WSL 2 containers.
Figure 2. A diagram of the WDDM model supporting CUDA user mode driver running inside Linux guest.
如果是从Microsoft Windows Insider程序的Fast Ring(build 20149或更高版本)在最新的Windows版本上安装了WSL发行版并将容器设置为以WSL 2模式运行的开发人员,并且如果是PC中NVIDIA GPU的受启发所有者,则可以尝试该驱动程序并在WSL 2中运行工作负载。只需在Windows主机操作系统上安装驱动程序,然后打开WSL容器。CUDA将在那里与CUDA应用程序一起工作,而不需要任何额外的努力。图3显示了在WSL 2容器中运行CUDA TensorFlow工作负载的屏幕截图。
WSL中的GPU为当前仅在本机Linux环境中运行的各种CUDA计算应用程序打开了大门。
英伟达仍在积极地进行这一项目,并作出调整。除此之外,正在努力将以前特定于Linux的api引入WDDM层,以便越来越多的应用程序可以开箱即用地处理WSL。
另一个焦点是表现。如前所述,WSL 2 GPU支持极大地利用了GPU-PV,可以影响较小的GPU工作负载,而无需任何流水线。现在,正在尽可能减少这些开销。
NVML不包含在初始驱动程序包中,对此存在一些问题。为了解决这个问题,计划将NVML和其库一起引入WSL。
首先启动了核心CUDA驱动程序,让可以在这个早期预览中尝试大部分现有的工作负载。意识到一些容器和应用程序甚至在加载CUDA之前就利用NVML查询GPU信息。这就是为什么把NVML放在WSL的首要任务中。请继续关注此主题的更多更新。
除了DirectX和CUDA支持之外,NVIDIA还在WSL 2中添加了对NVIDIA容器工具包(以前是NVIDIA-docker2)的支持。数据科学家准备在Linux本地硬件下运行或在云中执行的容器化GPU工作负载,现在可以在Windows PC上的WSL2中运行。
不需要特定的WSL包。NVIDIA运行时库(libnvidia容器)可以动态检测libdxcore,并在具有GPU加速的WSL 2环境中运行时使用。这是在Docker和NVIDIA容器工具包包安装之后自动发生的,就像在Linux上一样,允许GPU加速的容器以开箱即用的方式运行。
建议使用Docker工具的最新版本(19.03或更高版本),以利用对--gpus选项的额外支持。要启用WSL 2支持,请按照针对Linux发行版的GitHub repo上的自述步骤进行操作,并安装可用的最新版本。
那么是如何工作的呢?所有特定于WSL 2的工作都由libnvidia容器库处理。这个库现在能够在运行时检测libdxcore.so文件并用来检测所有暴露在这个接口上的gpu。
如果需要在容器中使用这些gpu,则使用以下命令查询驱动程序存储的位置:包含Windows主机和WSL 2的所有驱动程序库的文件夹libdxcore.so文件. 这取决于libnvidia-container设置容器以便正确映射驱动程序存储,并为WSL 2 GPU支持的核心库进行设置,如图4所示。
Figure 4. Discovery and mapping scheme used by libnvidia-container.so on WSL 2.
而且,这与WSL之外使用的逻辑不同。这完全是由libnvidia-container.so抽象出来的-对最终用户来说应该尽可能透明。此早期版本的一个限制是在多GPU环境中缺少GPU选择:容器中始终可见所有GPU。
以下是可以在WSL容器中运行的内容:目前熟悉的任何NVIDIA Linux容器。NVIDIA支持专业人士使用的大多数现有Linux工具和工作流。从NVIDIA NGC下载最喜欢的容器工作负载并进行尝试。
在下一节中,将描述如何在WSL 2中运行TensorFlow和n-body容器,同时使用NVIDIA GPUs加速工作负载。
使用Docker安装脚本安装Docker:
user@PCName:/mnt/c$ curl https://get.docker.com | sh
安装NVIDIA容器工具包。从nvidia-docker2 v2.3和底层运行库libnvidia container 1.2.0-rc.1开始,就提供了WSL 2支持。
建立稳定的实验库和GPG密钥。支持WSL 2的运行时更改在实验存储库中可用。
user@PCName:/mnt/c$ distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
user@PCName:/mnt/c$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -
user@PCName:/mnt/c$ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
user@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
安装NVIDIA运行时包及其依赖项:
user@PCName:/mnt/c$ sudo apt-get update
user@PCName:/mnt/c$ sudo apt-get install -y nvidia-docker2
打开WSL容器并在那里启动Docker守护进程。应该看到dockerd服务输出。
user@PCName:/mnt/c$ sudo dockerd
physical GPU (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0, compute capability: 6.1)" src="file:///C:/Users/JIANMI~1.HAS/AppData/Local/Temp/msohtmlclip1/01/clip_image010.gif" border="0" v:shapes="图片_x0020_13">
Figure 5. Starting the Docker daemon.
在另一个WSL容器窗口中,下载并启动N-body仿真容器。确保用户有足够的权限下载容器。可能需要在sudo中运行以下命令。GPU在输出中突出显示。
user@PCName:/mnt/c$ docker run --gpus all nvcr.io/nvidia/k8s/cuda-sample:nbody nbody -gpu -benchmark
Figure 6. Starting the N-body simulation container.
尝试另一个流行的容器:WSL 2中Docker中的TensorFlow。
下载TensorFlow Docker图像。为了避免Docker连接问题,该命令在sudo中运行。
user@PCName:/mnt/c$ docker pull tensorflow/tensorflow:latest-gpu-py3
保存稍微修改过–使用主机驱动器C上TensorFlow教程中的GPU,默认情况下,该驱动器在WSL2容器中映射为/mnt/C。
user@PCName:/mnt/c$ vi ./matmul.py
import sys
import numpy as np
import tensorflow as tf
from datetime import datetime
device_name = sys.argv[1] # Choose device from cmd line. Options: gpu or cpu
shape = (int(sys.argv[2]), int(sys.argv[2]))
if device_name == "gpu":
device_name = "/gpu:0"
else:
device_name = "/cpu:0"
tf.compat.v1.disable_eager_execution()
with tf.device(device_name):
random_matrix = tf.random.uniform(shape=shape, minval=0, maxval=1)
dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix))
sum_operation = tf.reduce_sum(dot_operation)
startTime = datetime.now()
with tf.compat.v1.Session(config=tf.compat.v1.ConfigProto(log_device_placement=True)) as session:
result = session.run(sum_operation)
print(result)
# Print the results
print("Shape:", shape, "Device:", device_name)
print("Time taken:", datetime.now() - startTime)
在GPU和CPU上运行此脚本的结果如下所示,该脚本是从安装的驱动器C启动的。为了简单起见,减少了输出。
user@PCName:/mnt/c$ docker run --runtime=nvidia --rm -ti -v "${PWD}:/mnt/c" tensorflow/tensorflow:latest-gpu-jupyter python /mnt/c/matmul.py gpu 20000
Figure 7. Running the matmul.py script.
当在WSL 2容器中使用GPU进行先前的计算场景时,会有显著的加速。
下面是另一个演示,看看GPU加速的工作:Jupyter笔记本教程。当容器启动时,应该会看到打印到笔记本服务器的链接。
user@PCName:/mnt/c$ docker run -it --gpus all -p 8888:8888 tensorflow/tensorflow:latest-gpu-py3-jupyter
Figure 8. Launching the Jupyter notebook.
现在应该可以在Jupyter笔记本上运行演示示例了。连接到笔记本时,请小心使用Microsoft Edge浏览器中的localhost,而不是127.0.0.1。
导航到tensorflow教程并运行分类.ipynb笔记本。
要查看Windows PC的GPU加速的工作,请导航到“单元格”菜单,选择“全部运行”,然后检查Jupyter笔记本的WSL 2容器中的日志。
physical GPU (device: 0, name: GeForce GTX 1070, pci bus id: 0000:01:00.0, compute capability: 6.1)" src="file:///C:/Users/JIANMI~1.HAS/AppData/Local/Temp/msohtmlclip1/01/clip_image018.gif" border="0" v:shapes="图片_x0020_27">
Figure 9. The Jupyter notebook log.
这个演示和这个容器中的其一些演示突出了小提交的虚拟化层当前的开销问题,前面也提到过。与这些玩具模型相关联的提交会导致GPU运行时比同步开销本身要短。在WSL 2上的这些极小型模型案例中,CPU时间可能比GPU时间更好。目前正在对其进行优化,并应仅限于较小的非流水线工作负载。
为了了解GPU是如何添加到WSL 2的,现在讨论Windows上的Linux是什么以及硬件是如何暴露给容器的。
微软在2016年的构建会议上引入了WSL。很快获得了发展势头,并成为Linux开发人员中的一个流行工具,希望在运行Linux开发工具和目标工作负载的同时运行Office等Windows应用程序。
WSL 1允许运行未修改的Linux二进制文件。但是,仍然使用Linux内核仿真层,是作为NT内核内的子系统实现的。该子系统通过将来自Linux应用程序的调用转发到相应的Windows 10功能来处理这些调用。
WSL 1是一个很有用的工具,但并不兼容所有的Linux应用程序,因为需要模拟可能每个Linux系统调用。一般来说,文件系统的访问也很慢,这导致了一些实际应用程序无法接受的性能。
考虑到这一点,微软决定走另一条路,推出了WSL 2,一个新版本的WSL。WSL 2容器在虚拟化环境中运行完整的Linux发行版,同时仍然充分利用Windows 10新容器系统的优点。 虽然使用Windows 10的Hyper-V服务,WSL 2仍然不是一个传统的VM,而是一个轻量级的实用VM。该实用程序管理虚拟地址备份内存,允许wsl2容器从主机Windows系统动态分配内存。
WSL 2的一些主要目标是提高文件系统性能并支持完全的系统调用兼容性。还具有更好的整体Windows主机系统集成。允许从Windows shell到运行在容器内的Linux系统的快捷方式,以及对自动装载到容器文件系统的选定目录的主机文件系统的访问。
WSL2作为WindowsInsider程序的预览功能启用,并作为最新的Windows10更新版本2004发布。
在最新的Windows版本中,WSL 2容器有了更多的改进,从网络堆栈到底层存储VHD。描述所有细节将超出本文的范围。有关WSL 2容器的一些有趣和令人兴奋的新特性的更多信息,请参阅比较wsl2和WSL 1。
WSL 2中的Linux内核是由微软基于kernel.org网站. 这个内核专门针对WSL 2进行了调整,针对大小和性能进行了优化,以在Windows上提供Linux体验。内核由Windows Update提供服务,这意味着无需自己管理即可获得最新的安全修复和内核改进。
微软在WSL中支持几个Linux发行版。遵循开放源代码社区的规则,WSL2内核源代码是公共的,可以在WSL2 Linux内核GitHub repo上使用,其中包含允许系统与Windows 10主机集成所需的修改。
微软开发人员正在通过GPU-PV技术将真正的GPU硬件支持引入WSL 2容器,在那里OS图形内核(dxgkrnl)将运行在guest VM内的用户模式组件调用封送到主机上的内核模式驱动程序。
在独立硬件供应商(IHV)的帮助下,微软开发了这项技术,作为其WDDM图形驱动程序模型的一项功能。NVIDIA图形驱动程序自Windows操作系统的Windows Insider程序中的功能预览早期起就支持GPU-PV。所有当前支持的NVIDIA gpu都可以暴露给运行在Hyper-V VM guest中的Windows操作系统。
对于WSL 2能够利用GPU-PV的能力,微软必须在Linux客户机中实现其图形框架的基础:使用GPU-PV协议的WDM模型。新的微软驱动程序支持Linux上的WDDM模型dxgkrnl。还可以作为WSL2 Linux内核GitHub repo中的源代码项目使用。
dxgkrnl驱动程序有望为WDDM 2.9版本的wsl2容器带来对GPU加速的支持。微软解释说,dxgkrnl是一个基于GPU-PV协议的Linux GPU驱动程序,与同名的Windows驱动程序没有任何共同之处。
目前,可以下载预览版的NVIDIA WDDM 2.9驱动程序。在接下来的几个月里,NVIDIA WDDM 2.9驱动程序将从Windows Update的WIP版本中分发,这使得手动下载和安装驱动程序变得不必要。
dxgkrnl驱动程序在Linux guest中将新的/dev/dxg设备公开给用户模式。D3DKMT内核服务层已经在Windows上提供,也作为dxcore库的一部分被移植到Linux上。使用一组私有IOCTL调用与dxgkrnl通信。
来宾Linux版本的dxgkrnl使用多个虚拟机总线通道连接到Windows主机上的dxg内核。主机上的dxg内核对待Linux进程提交的方式与运行在WDDM模型中的本地Windows应用程序提交进程的方式相同。将发送到KMD(一个特定于IHV的内核模式驱动程序),KMD准备并将提交给硬件GPU。图10显示了这种通信信道的简化图。
Figure 10. A simplified diagram showing Windows host components backing the new graphics dxg device in Linux guest.
NVIDIA驱动程序在许多版本中都支持Windows 10 GPU-PV和Windows来宾。NVIDIA GPU可用于在所有使用Microsoft虚拟化层的最终用户Windows 10应用程序中加速计算和图形,并使用GPU-PV功能添加vGPU:
11显示了在NVIDIA GeForce GTX 1070 GPU上的Windows沙盒容器中运行示例DirectX应用程序的示例。
Figure 11. Windows Sandbox container gets GPU acceleration on an NVIDIA GeForce GTX 1070 GPU.
为了在WSL中启用图形,Windows图形团队还将一个用户模式组件移植到Linux:dxcore。
dxcore库提供了一个API函数,用于枚举系统中符合WDDM的图形适配器。旨在作为Windows和Linux中DXGI适配器枚举的跨平台、低级替代品。还使用D3DKMT层API抽象了对dxgkrnl服务(Linux上的IOCTLs和Windows上的GDI调用)的访问,CUDA和其依赖WSL中WDDM模型支持的用户模式组件使用该API。
据微软称,dxcore(libdxcore.so文件)库将在Windows和Linux上都可用。NVIDIA计划在驱动程序中添加对DirectX 12和cudapi的支持,目标是WDDM 2.9模型的新WSL特性。两个API库都将链接到dxcore,以便可以指示dxg内核将请求封送到主机上的KMD。
如果想使用Windows PC在Linux环境中进行真正的ML和AI开发,WSL中对CUDA的支持将为带来一个令人兴奋的机会。WSL是Docker CUDA容器被证明是数据科学家中最流行的计算环境之一。
加入Microsoft Windows Insider程序以访问启用GPU加速的WSL 2预览。
下载最新的NVIDIA驱动程序,安装,并尝试在WSL 2中运行CUDA容器化工作负载。
手机扫一扫
移动阅读更方便
你可能感兴趣的文章