最近、自宅PCとして強いマシンを購入(intel i9 12900KS, DDR4 3200 128GB, RTX3090)しました。累計52万円とかなりお高い(電気代も高い)ですが、非常に快適です。
ゲームなどもしたいのでWindows 10にしましたが、せっかく良いGPUを積んでいるので、WSL2にpytorch環境を作ろうと思います。WSL2への接続方法は、以下の記事を参考にしています。
WSL2
WSL2はWSL1とネットワーク構成が異なり、直接sshをするのが困難です。ポートフォワーディングを行う必要があります。
WSL2のインストールは公式ドキュメントに従って行うが良いです。何も考えずにWindowsストアからUbuntuを入れるとWSL1が入るかと思います。自分はそこでWSL1からWSL2にアップグレードする際に、詰まり時間をロスしました。カーネルのアップグレードが必要となります。
SSH serverの設定
WSL2が入ったらopenssh-server
の設定をしておきます。
sudo apt update sudo apt install openssh-server
あとは公開鍵の設定などをしてログインできるようにしておきます。WSLの場合は
ssh user@localhost
でもログインできるようになります。
WSL-CUDA
WSLのCUDA Tool kitはNvidia公式から入れることができます。
CUDA Toolkit 11.6 Update 2 Downloads | NVIDIA Developer
Windows ポートフォワーディング
次に管理者権限でWindows側のPowershellを開きます。Ubuntu-20.04の場合を記載します。wsl -l -v
で自身のバージョンは確認できます。
wsl -d Ubuntu-20.04 -u root exec service ssh start $IP=wsl -d Ubuntu-20.04 exec hostname -I netsh.exe interface portproxy reset netsh.exe interface portproxy add v4tov4 listenport=22 connectaddress=$IP connectport=22 netsh.exe interface portproxy add v4tov4 listenport=8888 connectaddress=$IP connectport=8888 # IP Helperサービスの起動 sc.exe config iphlpsvc start=auto # ブート時の自動設定 sc.exe start iphlpsvc # サービスの起動
1行目でWSLのopen-sshserverを起動します。 2行目でWSLの内部IPを取得します。WSLを起動しなおすと毎回IPが異なってしまうため、そのたびにIPを取得する必要があります。 3行目はポートフォワーディングをリセットします。これは以下のように直接削除してもよいかと思います。
netsh.exe interface portproxy delete v4tov4 listenport=22 listenaddress=*
4, 5行目でポート22や8888のポートを聞き、WSL2のアドレス:ポートに転送してくれます。そのため、外部PCからWindows側にsshやhttp://PC名:8888にアクセスするだけでWSL側につなぐことができます。その際の注意点はWindows側でファイアウォールを開けておくことです。以下のコマンドで何が有効か確認できます。
PS C:\Users\name> netsh interface portproxy show all ipv4 をリッスンする: ipv4 に接続する: Address Port Address Port --------------- ---------- --------------- ---------- * 8888 172.21.119.130 8888 * 22 172.21.119.130 22 PS C:\Users\admin>
6, 7行目のコマンドでポートフォワーディングが有効になります。このスクリプトをportforward_wsl.ps1
とし、タスクスケジューラーでブート後に実行するようにすれば完成です。正しく設定されていれば、WSL2のubuntuに接続できるようになります。
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned ".\portfoward_wsl.ps1
最終的に
上記のようにしたところWindowsからWSLへの自動ポートフォワーディングとバッティングして上手くいかず、最終的に以下のようにしました。
$HOST_IP=192.168.1.2 # 例 netsh.exe interface portproxy reset netsh.exe interface portproxy add v4tov4 listenaddress=$HOST_IP listenport=22 connectaddress=localhost connectport=22 netsh.exe interface portproxy add v4tov4 listenaddress=$HOST_IP listenport=8888 connectaddress=localhost connectport=8888
WSL2の機能として、localhostに接続すると自動でWSL2のIPに転送してくれる機能がデフォルトでTrueとなっています。例えば、Jupyter notebookなどはhttp://localhost:8888
を入力すると自動でhttp://172.31.236.31:8888
のところに転送してくれているため、このアドレスに到達することができています。この172.31.236.31
はWSL2の内部IPになっています。結局、色々試しましたが、接続先IPからlocalhostに飛ばすようにしてあげればよいだけでした。これだと動的に変わるWSL2のIPを意識する必要はなくなりそうです。このスクリプトはタスクスケジューラに追加します。