WSL

      在〈WSL〉中尚無留言

WSL 簡介

WSL 全名為 Windows subsystem Linux,是微軟 Hyper-V 虛擬機器裏的一個輕量級子系統,可以在 Windows 裏跑 Linux 系統,而且支援 GPU-PV。GPU-PV 稱為顯卡虛擬化,是在 Linux 虛擬機上存取 Windows 宿主機硬体 GPU 的一種技術。這對沒有多餘機器安裝實体 Linux 的人而言,是蠻不錯的選擇。

WSL 僅支援 Windows 10/Windows 11 的 Professional(專業版) EnterPrise(企業版)若是Home(家用版),則無法使用。

安裝 WSL

以系統管理員身份啟動 Dos 視窗命令提示 ,執行如下指令安裝 wsl 系統

wsl --install

上面的指令除了安裝 wsl 子系統外,重新開機後,還會自動安裝 ubuntu 最新的版本。安裝 ubuntu 時需一段時間,請耐心請待。

安裝ubuntu 時,若出現 WslRegisterDistribution failed with error: 0x80370102 錯誤,請參考本篇最下面的核心隔離,然後重新開機,再執行如下指令

wsl --install -d ubuntu

GPU-PV

WSL2 支援 GPU-PV (顯卡虛擬化),所以 WSL2 一裝好,除了 ubuntu 一併裝進去,dxgkrnl 驅動程式也會自動裝好,馬上可以使用 “nvidia-smi” 這個指令測試。

nvidia-smi

Fri Apr 19 14:48:15 2024
+-------------------------------------------------------------------------------------+
| NVIDIA-SMI 550.76.01          Driver Version: 552.22         CUDA Version: 12.4     |
|-------------------------------------+------------------------+----------------------+
| GPU  Name             Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf      Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |
|                                     |                        |               MIG M. |
|=====================================+========================+======================|
|   0  NVIDIA GeForce RTX 3080 Ti  On |   00000000:01:00.0  On |                  N/A |
| 53%   43C    P8         60W /  400W |    1758MiB /  12288MiB |     13%      Default |
|                                     |                        |                  N/A |
+-------------------------------------+------------------------+----------------------+

+-------------------------------------------------------------------------------------+
| Processes:                                                                          |
|  GPU   GI   CI        PID   Type   Process name                          GPU Memory |
|        ID   ID                                                           Usage      |
|=====================================================================================|
|  No running processes found                                                         |
+-------------------------------------------------------------------------------------+

有看到上面的訊息,表示GPU-PV 驅動程式已經安裝完成。

與 VMware相衝

wsl 一打開,市面上常用的 vmware, viturebox 馬上失效,這是因為 “Windows 子系統 Linux 版” 及 “虛擬機器平台” 被打開了,造成 VMware 的 Vituralize Intel VT-x/EPT 無法啟用。請由 “開始/Windows 系統/控制台/程式集/開啟或關閉 Windows 功能” 進入查看。

Vituralize Intel VT-x/EPT 加速虛擬機的技術,若要重新啟用 VMware的 Vituralize Intel VT-x/EPT,請將如下紅線框起來的功能全部都取消。

當然上面的功能關掉,WSL 就無法用。所以如果想要 VMware 與 WSL 共存並用,可以考慮將 VMware的 Virtualize Intel VT-X/EPT 取消,這樣VMware 就又可以執行了,只是速度可能會比較慢。

啟動 Ubuntu

開啟 Dos 視窗,輸入如下指令即可

wsl -d ubuntu

移除 Ubuntu

移除 ubuntu 請執行如下指令。

wsl --unregister ubuntu

手動安裝 Ubuntu

如果要重新安裝或手動安裝其它 ubuntu,進入 Dos 視窗輸入

wsl --install -d ubuntu

移除 WSL

要移除 WSL 請先確認如下步驟

wsl --unregister ubuntu
wsl --shutdown
wsl --uninstall
控制台關掉 windows 子系統 Linux
重新開機

預設安裝路徑

WSL 預設安裝在 C 碟如下目錄

C:\Users\mahal\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState

搬移安裝位置

通常我們不會把 utuntu 安裝在 C 碟,所以要作搬移的動作,請依續執行如下指令

wsl --shutdown
wsl --export Ubuntu d:\ubuntu.tar
wsl --unregister Ubuntu
d:
mkdir wsl
wsl --import Ubuntu d:\wsl d:\ubuntu.tar
del d:\ubuntu.tar

搬移後打開 wsl 進入 ubuntu,卻發現登入的帳號是 root。

請在 開始 按右鍵,執行 regedit,依序進入如下位置

 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxx}

然後將 DefaultUid 改成十進位的 1000,最後重新執行 wsl 即會用一般使用者登入。

ubuntu 初始設定

一開始要初始的設定如下

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install net-tools network-manager ubuntu-drivers-common
sudo apt-get install nvidia-cuda-toolkit

核心隔離

WSL2 有時會出現 WslRegisterDistribution failed with error: 0x80370102 錯誤,網路常教大家切換到 WSL1 即可,但這樣就無法支援 GPU-PV,唯一的方法就是重新安裝 Windows,這應該是微軟的嚴重bug。

若緊急狀況不能重新安裝 Windows ,可以將核心隔離暫時開啟,就可以跑 wsl2 了,但核心隔離一但開啟,整台電腦的效能就會降低很多,由其是 “雷電” 或 “BlueStacks” 等 Android 模擬器更為嚴重,而且 VMware 及 VirtualBox 就無法執行了。所以想要執行其它虛擬器,核心隔離就要再度手動關閉,然後重心開機。

開啟核心隔離的方法,請由 Windows 安全性/裝置安全性/核心隔離/記憶体完整性將之打開,如下圖所示

Hyper-V 虛擬機

使用 Hyper-V 當虛擬機的原因是它可以啟用硬体 GPU。

雖說 VMware 也可以啟動硬体 GPU,但必需加裝 vSphere 套件。Sphere[sfɪr] 是球型、領域的意思,vSphere 可以翻譯成虛擬領域 VMware 在 2024年2月取消 vSphere 的免費版本,造成全球的經銷商大出走,不想再替 VMware 出售它們的軟体。

另外 Hyper-V 使用系統服務可於開機時自動啟動,不像 VMware 還要自已撰寫服務程式,所以 Hyper-V 看起來方便許多。

那為什麼不直接使用 WSL 呢! WSL 雖說啟動快,但只能使用 NAT,無法取得跟宿主機同網域的 IP,所以不能架設網站,它只是工程師暫時取代實機 Linux 的一個小工具而以。

另有件要注意的事項,市面常見的 Android 模擬器,比如 BlueStack, 雷電等,為了加速效能,會自動把 Windows 的 Hyper-V 及虛擬機器平台關掉,所以為了能正常執行虛擬機,請把 Andorid 模擬器全都移除乾淨,不要再浪費時間在線上遊戲了。

安裝 Hyper-V

開始/Windows 系統/控制台/程式集/開啟或關閉 Windows 功能,將 Hyper-V 勾選,然後重新開機。

然後開啟 “開始/Windows 系統管理工具/Hyper-V 管理員“,連線到伺服器,選擇本機電腦。

建立虛擬交換器

虛擬交換器是為了得到一個能產生 bridge (橋接器) 的虛擬網卡。請選取虛擬交換器管理員,選外部,再按下建立虛擬交換器,名稱填入 HV_Bridge

此時打開網卡設定視窗,多了 vEthernet(Default Switch)vEthernet(HV_Bridge) 二張虛擬網卡

建立虛擬機

按下新增/虛擬機器,虛擬機名稱輸入 “Ubuntu“,勾選將虛擬機儲存在不同位置,然後選其它磁碟機。

接下來的畫面,因Ubuntu 映像檔無法用 UFEI 開機,所以要選第1代

再來設定啟動記憶体,因為本人的宿主機有64G,所以就設定為 16384MB,然後很重要的一點,就是 為此虛擬機器使動態記憶体 要取消,不然硬体 GPU 無法啟動。

接下來的連線選 “HV_Bridge”,建立虛擬硬碟的大小設定為 1024 GB,安裝作業系統選映像檔,然後選取 ubuntu 的 iso 檔。

上述設定完成後,還沒開始安裝。先在 Ubuntu 按右鍵/設定,處理器的虛擬處理器數目改成4~8。

然後就可以按下連線並啟動,開始進行 Ubuntu 的安裝。

增加 GPU-PV 硬件

虛擬機 Ubuntu 並不是直接存取 Windows 宿主機的 GPU,而是在 Ubuntu 中裝上 GPU-PV 這個虛擬硬體,然後啟用 dxgkrnl 驅動程式並使用 DirectX 與宿主機 GPU 溝通。GPU-PV 其實是顯卡虛擬化的意思。新增 GPU-PV 硬体之前,必需把檢查點的功能取消,否則虛擬機會說新增了 GPUP 而無法執行。請在 Ubuntu虛擬器按右鍵/設定,在檢查點項目中,把啟用檢查點取消,最後記得要把虛擬機關機

然後在 Windows 宿主機使用系統管理員身份開啟 PowerShell,執行如下指令。請注意,只能用 PowerShell,不可以用 DOS 視窗。

Set-VM -VMName <vmname> -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace 1GB -HighMemoryMappedIoSpace 32GB
Add-VMGpuPartitionAdapter -VMName <vmname>

上面的 <vmname> 就是我們虛擬器的名稱 “Ubuntu”。所以實際指令如下

Set-VM -VMName Ubuntu -GuestControlledCacheTypes $true -LowMemoryMappedIoSpace 1GB -HighMemoryMappedIoSpace 32GB
Add-VMGpuPartitionAdapter -VMName Ubuntu

接下來打開 HV 虛擬器,輸入 lspci,就會看到多了 “3D controller: Microsoft Corporation Device 008e”,這就表示 GPU-PV 新增成功。

執行 sudo lshw -C display,就會看到新增底下紅色的框框的硬体,只是目前沒有驅動程式

安裝 dxgkrnl 驅動程式

dxgkrnl 是 GPU-PV 的驅動程式,使用 DirectX 與 Linux 溝通,底下的 dxgkrnl 是由微軟維護的,比較穩定。先安裝如下套件

sudo apt install build-essential flex bison dwarves libssl-dev libelf-dev

然後在虛擬機查看 Ubuntu 目前的 kernel  版本

uname -r

結果:
5.15.0-105-generic

vim dx.sh,輸入如下代碼。請注意藍色的部份要跟上面所查到的 Ubuntu 核心版本一致,否則會讓虛擬機當機。

#!/bin/bash -e
BRANCH=linux-msft-wsl-5.15.y

if [ "$EUID" -ne 0 ]; then
    echo "Swithing to root..."
    exec sudo $0 "$@"
fi

apt-get install -y git dkms git clone -b $BRANCH --depth=1 https://github.com/microsoft/WSL2-Linux-Kernel cd WSL2-Linux-Kernel VERSION=$(git rev-parse --short HEAD) cp -r drivers/hv/dxgkrnl /usr/src/dxgkrnl-$VERSION mkdir -p /usr/src/dxgkrnl-$VERSION/inc/{uapi/misc,linux} cp include/uapi/misc/d3dkmthk.h /usr/src/dxgkrnl-$VERSION/inc/uapi/misc/d3dkmthk.h cp include/linux/hyperv.h /usr/src/dxgkrnl-$VERSION/inc/linux/hyperv_dxgkrnl.h sed -i 's/\$(CONFIG_DXGKRNL)/m/' /usr/src/dxgkrnl-$VERSION/Makefile sed -i 's#linux/hyperv.h#linux/hyperv_dxgkrnl.h#' /usr/src/dxgkrnl-$VERSION/dxgmodule.c echo "EXTRA_CFLAGS=-I\$(PWD)/inc" >> /usr/src/dxgkrnl-$VERSION/Makefile cat > /usr/src/dxgkrnl-$VERSION/dkms.conf <<EOF PACKAGE_NAME="dxgkrnl" PACKAGE_VERSION="$VERSION" BUILT_MODULE_NAME="dxgkrnl" DEST_MODULE_LOCATION="/kernel/drivers/hv/dxgkrnl/" AUTOINSTALL="yes" EOF dkms add dxgkrnl/$VERSION dkms build dxgkrnl/$VERSION dkms install dxgkrnl/$VERSION

儲存後,執行如下指令

sudo chmod 755 dx.sh
sudo ./dx.sh

上述代碼的用途是編譯及安裝 dxgkrnl 驅動,有時會編譯錯誤,需重複執行幾次,一直看到有出現 depmod…. 才表示安裝成功,如下圖所示。

將虛擬機重新開機後執行 sudo lshw -C display,即可看到驅動裝起來了

安裝套件

先把 Windows 宿主機底下二個目錄 copy 到 虛擬機的家目錄下。有的人使用 scp copy,本人則是使用 winscp ,比較方便。

C:\Windows\System32\lxss\lib
C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_xxxxxx

nv_dispi.inf_amd64 後面的 xxx 每台機器都不一樣。

然後執行如下指令

sudo mkdir -p /usr/lib/wsl/{lib,drivers}
sudo cp -r lib/* /usr/lib/wsl/lib/
sudo cp lib/nvidia-smi /usr/bin
sudo chmod 755 /usr/bin/nvidia-smi
sudo cp -r nv_dispi.inf_amd64_* /usr/lib/wsl/drivers/
sudo chmod -R 0555 /usr/lib/wsl
sudo ln -s /usr/lib/wsl/lib/libd3d12core.so /usr/lib/wsl/lib/libD3D12Core.so

接下來執行 sudo vim /etc/ld.so.conf.d/ld.wsl.conf,加入如下

/usr/lib/wsl/lib

最後還要執行如下指令

 sudo ldconfig

上述如果出現 “/sbin/ldconfig.real: /usr/lib/wsl/lib/libcuda.so.1 is not a symbolic link”,請不用理會。

測試

終於安裝完成了,請執行 nvidia-smi ,就可以看到如下畫面了

開機自動啟動虛擬機

停止虛擬機,在虛擬機按右鍵/設定,左邊的自動啟動動作,選擇永遠自動啟動此虛擬機器

然後在自動停止動作選項中,選取關閉虛擬機器

怪異現像

Hyper-V 安裝 Ubuntu 後,然後於 Windows 宿主機安裝 MySQL Community Server,會發生 mysql80 因為 3306 port 被佔住無法安裝,換了其它 port 一樣裝不起來。最終發現把 Ubuntu 虛擬機關機,就能成功安裝 MySQL。

接下來重新開機再進行測試,Hyper-V 也正常, MySQL 也正常。這真的是太詭異了,只能說 Hyper-V 的 bug 何其多,實在有待加常。

說老實話,林北本來就有實体的 Linux 伺服器,而且也有實体的 RTX-3080Ti 顯卡,壓根兒就不用去搞這種問題一大堆的 Hyper-V 虛擬機。

沒法度,前世業障過深,今世被指定天命需以教學普渡眾生,所以只好補上這篇。

另外還有個 issue,就是 Asus 控制及監控 GPU 的 Tweak III ,好像有很大的問題。還沒安裝 Hyper-V 前就會偶發黑屏停頓個5、6秒,裝了 Hyper-V 後更是隨性的發狂,目前本人先把 Tweak 移除進行測試中。

參考

https://gist.github.com/krzys-h/e2def49966aa42bbd3316dfb794f4d6a

Hyper-V 及 WSL 安裝 Cuda

無論是在 Hyper-V 或是 WSL,安裝 nVidia 的 Cuda 及 cudnn 的步驟是一樣的。

但在開始安裝 Cuda 時,一定要把虛擬機的硬体驅動程式安裝好,請執行 nvidia-smi,看到如下的畫面才可繼續安裝 Cuda。

安裝 Cuda

到官網 https://developer.nvidia.com/cuda-toolkit-archive 查看相關版本的安裝指令。底下是 cuda 12.4.0 的版本,請選擇 Linux/x86_64/WSL-Ubuntu/2.0/deb(local)。底下是官網說明的安裝方式。

wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-wsl-ubuntu.pin
sudo mv cuda-wsl-ubuntu.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/12.4.0/local_installers/cuda-repo-wsl-ubuntu-12-4-local_12.4.0-1_amd64.deb
sudo dpkg -i cuda-repo-wsl-ubuntu-12-4-local_12.4.0-1_amd64.deb
sudo cp /var/cuda-repo-wsl-ubuntu-12-4-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update
sudo apt-get -y install cuda-toolkit-12-4

安裝 cudnn

安裝 cudnn 時, 請勿依官網的方式下載及安裝,只需使用 apt-get install 即可,安裝套件如下。

sudo apt-get -y install nvidia-cudnn

安裝的第一個畫面請按 “OK”

第二個畫面,請選取 “I Agree”,然後再按 “OK”

驗証 GPU 是否啟動

請先在 Python 專案下安裝套件

sudo apt-get install python3.10-venv
mkdir pytest
cd pytest
python3 -m venv .venv
source ./.venv/bin/activate
pip install tensorflow

然後編寫測試程式,vim test.py

import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
import tensorflow as tf
gpus = tf.config.list_physical_devices(device_type='GPU')
print(gpus)

最後執行,python test.py,得到如下的結果就表示硬体 GPU 啟動了

[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

蒙地卡羅測試

執行如下的蒙地卡羅程式,可以看到 GPU 全速在執行。

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
import tensorflow as tf
batch=100_000_000
epochs=2000
incircle=0
#@tf.function
def cal():
    points=tf.random.uniform([2, batch], dtype=tf.float32)
    dist=tf.sqrt(tf.square(points[0])+tf.square(points[1]))
    count=tf.where(dist<=1).shape[0]
    return count
# cpus = tf.config.list_physical_devices (device_type='CPU')
# tf.config.set_visible_devices (devices=cpus[0]) #只使用 CPU, device_type預設是'CPU'
for e in range(epochs):
    count=cal()
    incircle+=count
    area=incircle /((e+1)*batch)
    pi=area*4
    print(f'epoch:{e+1}, pi={pi}')

上述程式開始跑時,開啟另一個視窗執行如下指令

watch -n 1 nvidia-smi

就可以看到顯卡的功耗到了 355瓦

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *