適用於Linux 2的Windows子系統上的CUDAhtml
Announcing CUDA on Windows Subsystem for Linux 2python
爲了響應大衆的需求,微軟在2020年5月的構建會議上宣佈了WindowsSubsystem for Linux2(WSL2)的一個新特性——GPU加速。這一特性爲許多計算應用程序、專業工具和工做負載打開了大門,目前只有Linux纔有,但如今能夠在Windows上按原樣運行,並從GPU加速中獲益。 git
最重要的是,NVIDIA CUDA加速度如今來到了WSL。在這篇文章中,將討論在WSL 2的公共預覽中對CUDA的指望。github
WSL是Windows 10的一個特性,使可以直接在Windows上運行本機Linux命令行工具,而不須要複雜的雙引導環境。在內部,WSL是一個與Microsoft Windows操做系統緊密集成的容器化環境。這使得能夠在傳統的Windows桌面和現代商店應用程序的同時運行Linux應用程序。 docker
WSL主要是開發人員的工具。若是正在Linux容器中處理計算工做負載,則可使用熟悉的本地Linux工具在Windows PC上本地開發和測試工做負載。一般,這些應用程序須要大量的黑客、第三方框架和庫才能在Windows系統上運行。全部這些都隨WSL 2而改變,WSL 2爲Windows世界帶來了完整的Linux內核支持。 shell
藉助WSL 2和GPU半虛擬化(GPU-PV)技術,微軟正在爲Windows上的Linux支持添加另外一個功能,容許運行鍼對GPU硬件的計算工做負載。在本文後面,將更詳細地介紹WSL 2以及GPU是如何添加到其中的。 編程
有關更多信息,請參見DirectX進入Windows Linux子系統和GitHub中的WSL2 Linux Kernel/driver/gpu目錄。windows
要利用WSL 2中的GPU,目標系統必須安裝支持Microsoft WDDM模型的GPU驅動程序。這些驅動程序由NVIDIA等GPU硬件供應商提供。 api
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容器化工做負載。