ゲーミングPCで始める量子化学計算

# 結論
1. ゲーミングPCでも量子化学計算は可能
1. GPUを使うことで約6倍速で計算できる
1. Dockerのおかげで環境構築も簡単にできる

# 環境
| Machine1 | Machine2 |
| -------- | -------- |
| Ubuntu22.04 (WSL2) | Ubuntu22.04 (WSL2) |
| GeForce RTX 2070 super | GeForce RTX 4090 |
| VRAM 8GB | VRAM 24GB |
| Intel Core i5 12400F | Intel Core i7 9700F |
| RAM 16GB | RAM 16GB |
| SSD (M.2) | SSD (SATA) |

　これらにフリーの量子化学計算ソフトの[GAMESS](https://www.msg.chem.iastate.edu/gamess/capabilities.html)をインストールしてベンチマークを実行してみます。有機分子サイズの計算に必要なメモリはGAMESSのデフォルトの8メガワード = 64MBでたいてい事足りますし、ログファイルも<10MBくらいなので、計算速度さえ気にならなければ個人で量子化学計算に挑戦するのは十分可能です。

# GAMESSのインストール手順
　GPUを使用するためにDockerコンテナとして配布されているものを使用します。コンパイル不要で下準備が少ないので楽ちんです。おおまかに次の手順で進みます。
1. WindowsにUbuntuをインストール (WSL2)
1. Windowsに最新のNVIDIAドライバをインストール
1. WSL2にDockerをインストール
1. WSL2にNVIDIA Container Toolkitをインストール
1. WSL2にNVIDIA GPU Cloud (NGC)からGAMESSコンテナを引っ張ってくる

　NVIDIA Container Toolkitのインストールまでは[こちらの記事](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa)によくまとまってますが、私のような材料屋にはこれでも苦しかったので補足して説明します。

## WindowsにUbuntuをインストール (WSL2)
　Docker Desktopを使ってしまえばもっと楽みたいなのですが、どうせ操作はコマンドラインからになるのでWindows Subsystem for Linux 2 (WSL2)を使っていきましょう。

1. **管理者権限**でコマンドプロンプトかPowerShellを起動します。
1. `wsl --list --online`でインストール可能なLinuxのバージョンを確認します。(Ubuntu22.04とします）
1. `wsl --install -d Ubuntu22.04`でUbuntuをインストールします。
1. コマンドラインの指示に従ってユーザー名やパスワードを設定します。

　この手順は[Microsoftの公式手順](https://learn.microsoft.com/ja-jp/windows/wsl/install)を修正したものです。`wsl --install`でどのバージョンが入るか不明なのは、トラブルシューティングで困りそうなので指定するようにしました。

## Windowsに最新のNVIDIAドライバをインストール
　これは簡単ですね。ゲーミングPCを想定しているのでGeForce ExperienceでGame Readyドライバを入れてしまえばいいです。

## WSL2にDockerをインストール
　[Docker公式に従う](https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script)ならWSL2で次のコマンドを実行します。
```
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```
これを[NVIDIAの方の記事](https://qiita.com/ksasaki/items/ee864abd74f95fea1efa#cuda-toolkit-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)では一行で書いて`curl https://get.docker.com | sh`とされています。「Docker Desktop for Windowsを使え」と警告されますが無視です。
　なお初めてWSL2を使われた方の中には`Could not resolve host: get.docker.com`みたいなエラーが出るかもしれません。この場合は[こちらの記事](https://qiita.com/kkato233/items/1fc71bde5a6d94f1b982)に解決策があるので修正して上記コマンドを再実行して下さい。

## WSL2にNVIDIA Container Toolkitをインストール
　[NVIDIA公式の手順](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#setting-up-nvidia-container-toolkit)に従います。まずレポジトリとGPG keyを設定するらしいです。
```
distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
      && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
      && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
            sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
            sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
```
をWSL2で実行して下さい。そのまま続いて
```
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
```
でインストールできます。さらにDockerにNVIDIA Container runtimeを認識されるため？に
```
sudo nvidia-ctk runtime configure --runtime=docker
```
を実行らしいです。最後にDockerを再起動します。
```
sudo service docker restart
```
　`sudo systemctl restart docker`はたぶん使えないです。念のために正常にインストールできていることを確認します。
```
sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi
```
　もし
```
Failed to initialize NVML: GPU access blocked by the operating system
Failed to properly shut down NVML: GPU access blocked by the operating system
```
みたいなエラーが出てしまったら厄介です。[修正されたことになっているバグ](https://forums.developer.nvidia.com/t/failed-to-initialize-nvml-gpu-access-blocked-by-the-operating-system/174610)ですが私は出ました。私の場合は不要なはずのCUDA Toolkitをインストールしてみたら解決しましたが、[その前に再起動した方が正解](https://stackoverflow.com/questions/33834892/nvidia-smi-failed-to-initialize-nvml-gpu-access-blocked-by-the-operating-system)だったかもしれません。
　エラーが出ずにGPUの使用状況が出力されたらNVIDIA Container Toolkitのインストールは完了です。

### インストール確認でエラーが出てCUDA Toolkitをインストールしてみる場合
　CUDAのバージョン管理が面倒でDockerコンテナを使ってる側面があるのでお勧めはしません。そもそもコンテナイメージ内にあるCUDAを使うはずなのに、なぜこの手順を行ってうまくいったのか分かってません。
　PyTorchやTensorFlowなどを使う見込みが一切なければ[ガイド](https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=WSL-Ubuntu&target_version=2.0&target_type=deb_network)に従って最新版をインストールします。こちらはネットワーク版のコマンドです。
```
wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt-get updatesudo apt-get -y install cuda
```

　PyTorchやTensorFlowのために古いバージョンが必要な場合は[アーカイブ](https://developer.nvidia.com/cuda-toolkit-archive)からバージョンを選択し、そのバージョン用のガイドに従って下さい。ネットワーク版だと最新版と同じコマンドが表示されて不安になるため、ローカル版を選択する方が安心できるでしょう。
　CUDA Toolkitをインストールしたら**コマンドプロンプト**(ホストのwindows側)から
```
wsl --shutdown
wsl
```
でWSL2を再起動し、さらにWSL2で
```
sudo service docker restart
```
としてDockerを再起動しておきましょう。
　ここまで試して`sudo docker run --rm --runtime=nvidia --gpus all nvidia/cuda:11.6.2-base-ubuntu20.04 nvidia-smi`でエラーが出る場合は私にはお手上げなので、各人で頑張って下さい・・・。

## WSL2にNVIDIA GPU Cloud (NGC)からGAMESSイメージを引っ張ってくる
　非常に簡単です。[NVIDIAのGPU版GAMESS紹介ページ](https://www.nvidia.com/es-la/data-center/gpu-accelerated-applications/gamess/)を参考に
```
sudo docker run --gpus all -v $(pwd):/results --rm -it nvcr.io/hpc/gamess:17.09-r2-libcchem
```
でGPUを利用するGAMESSを実行できるコンテナが起動します。元は`nvidia-docker run`となってますが[古い方法で非推奨](https://medium.com/nvidiajapan/nvidia-docker-%E3%81%A3%E3%81%A6%E4%BB%8A%E3%81%A9%E3%81%86%E3%81%AA%E3%81%A3%E3%81%A6%E3%82%8B%E3%81%AE-20-09-%E7%89%88-558fae883f44)のため修正しました。

### GAMESSコンテナ起動のエイリアスの設定
　毎度長いコマンド打つのは嫌だし、そもそも覚えられないので[エイリアス(ショートカットコマンド)](https://qiita.com/miriwo/items/0a3bce6bb04aaca6a7a6)を設定します。
```
echo alias gamess='sudo docker run --gpus all -v $(pwd):/results --rm -it nvcr.io/hpc/gamess:17.09-r2-libcchem' >> ~/.bash_aliases
source ~/.bashrc
```
　`~/.bash_aliases`に記述することでエイリアスが設定できます。今回は`gamess`と打てば長いコマンドを打ったのと同じになります。

# ベンチマークの実行
## 結果
　先ほどの[NVIDIAのGPU版GAMESS紹介](https://www.nvidia.com/es-la/data-center/gpu-accelerated-applications/gamess/)の最下部でHPCサーバ向けCPUとGPUを比較してGPUの効果が示されているので、それらと比べてゲーミングPCの実力がどんなものかを見てみましょう。同じベンチマークを実行するにはWSL2で次のコマンドを実行します。
```
sudo docker run --gpus all -v $(pwd):/results --rm -it nvcr.io/hpc/gamess:17.09-r2-libcchem
cd /workspace/examples
rungms rimp2-valinomycin.spherical.energy.ccd_cct.inp
```
　さて紹介ページと私の結果を並べてみます。
| Proceccor | 2x Intel Xeon E5-2690 v4 | 1x Tesla P100 | 1x Tesla V100 | 1x RTX 2070 super | 1x RTX 4090 |
| --------- | ------------------------ | ---------- | ---------- | ---------------| ---------|
| Time/sec | 5072 | 639 | 744 | 890 | 844 |
| FP64/TFLOPS |  | 4.7[^1] | 7[^2] | 0.28[^3] | 1.29[^4] |

CPUは2基並列みたいです。また私が試したRTXシリーズは1回ずつしか計算していません。計算時間は必ずしも倍精度の計算速度(FP64)に従うわけではありませんでした。VRAMの速度やCPUとの接続速度などの影響でしょうか？なんにせよCPUより断然速くなるのは確かでした。**そもそもGAMESSが遅く、Intel CPUに最適化された[Firefly](http://classic.chem.msu.su/gran/gamess/)に変えると10倍速くなるらしいですが。**

[^1]:https://www.nvidia.com/ja-jp/data-center/tesla-p100/
[^2]:https://www.nvidia.com/en-gb/data-center/tesla-v100/
[^3]:https://www.techpowerup.com/gpu-specs/geforce-rtx-2070-super.c3440
[^4]:https://www.techpowerup.com/gpu-specs/geforce-rtx-4090.c3889

## ベンチマークの中身
　今回計算した内容を簡単に説明しておきましょう。対象とした分子は分子量が約1100の[バリノマイシン](https://ja.wikipedia.org/wiki/%E3%83%90%E3%83%AA%E3%83%8E%E3%83%9E%E3%82%A4%E3%82%B7%E3%83%B3)という抗生物質で、その全エネルギーを計算しています。結合距離や結合角などは予め与えられています。
　構造式だけ与えられた状態から同じように全エネルギーを計算してHOMOやLUMOの情報を得ようとすると、実際には構造最適化と振動解析を先に行う必要があります。構造最適化の手順については[こちらのサイト](http://pc-chem-basics.blog.jp/archives/422950.html)によくまとまっています。

# 結言
　この記事では計算速度と必要な計算資源を確認することで、GAMESSは個人の環境でも実践できることを示したつもりです。全然量子化学計算をやったことがないけど興味はあるという人間にとって、数多あるフリーソフトからどれを選ぶかというのがまず問題です。同様にFireflyやPySCF、psi4などでどなたかが似たような比較記事を書いて下さることを密かに期待しております。