グラフ機械学習と強化学習について

主にグラフ機械学習や強化学習手法を記載します。

WSL2にSSHをする

最近、自宅PCとして強いマシンを購入(intel i9 12900KS, DDR4 3200 128GB, RTX3090)しました。累計52万円とかなりお高い(電気代も高い)ですが、非常に快適です。

ゲームなどもしたいのでWindows 10にしましたが、せっかく良いGPUを積んでいるので、WSL2にpytorch環境を作ろうと思います。WSL2への接続方法は、以下の記事を参考にしています。

qiita.com

WSL2

WSL2はWSL1とネットワーク構成が異なり、直接sshをするのが困難です。ポートフォワーディングを行う必要があります。

WSL2のインストールは公式ドキュメントに従って行うが良いです。何も考えずにWindowsストアからUbuntuを入れるとWSL1が入るかと思います。自分はそこでWSL1からWSL2にアップグレードする際に、詰まり時間をロスしました。カーネルのアップグレードが必要となります。

docs.microsoft.com

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側にsshhttp://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を意識する必要はなくなりそうです。このスクリプトはタスクスケジューラに追加します。

https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=WSL-Ubuntu&target_version=2.0&target_type=deb_local