CP2KとそれをリンクしたGROMACSのビルド
この記事 is 何
最近、おうち化学計算でCP2Kをビルドしました。また、ずっと前からGROMACSは何かマシンを新調するたびにビルドしています。
となると、やることは一つですね。GROMACSからCP2Kをリンクし、QM/MM計算できるようにします。
環境
- OS: WSL上のUbuntu
- プロセッサ: core i7 14700F と RTX 5060 Ti
- CP2K: ビルド時の github のマスターブランチ(Commit:d5104b917ecbe5ed8f1e41b3dfe6fa49499b0b60)
- GROMACS: 2025.2
余計な事
それぞれのビルド時にRTX 5060 Ti (Blackwell)に最適化したコードを生成してみようと思います。
GromacsはCMAKEで compute_sm
に相当するオプション( CMAKE_CUDA_ARCHITECTURES
)に100とかを指定すればいいです。
CP2Kの方は厄介で、 toolchain のオプションにコードネームを渡してやればそれからif分岐で適切なオプションをMakefileに追加するのですが、 RTX 50シリーズの Blackwell は未対応です。とはいえ nvcc
の compute_sm
オプションに適切な数字を渡せればいいだけなので、ちょっと修正して対応します。この編集は特にプログラム本体の動作には影響しないと思いますが、念のためここで言及しておきます。
なおCP2Kのcuda版かつMPI版はビルドに失敗しました。
あと、GromacsにはCPU版、CUDA版の両方のCP2Kがリンクできます。まあ、CUDA版で早くなるところはたぶんQMMMでは使わない気がしますが。
準備
まず、FFTW, OpenMPI, BLAS, Lapack のdevelライブラリを apt からインストールしておきます。CP2Kの toolchain を使えば cp2k 内部でビルドしてくれて、CP2K だけで完結するならこれでも問題ないですが、GROMACSのリンク時には両者で共通のライブラリにする必要があり、このcp2k内部でビルドしたやつを見に行かなきゃいけないため、面倒です。
あと、とりあえずCP2KリンクしないGromacsを普通にCmakeからビルドできるか試して、そのほか必要なライブラリやコマンドがそろっているか確認しましょう。
CP2Kビルド
まずCP2Kのビルドから始めます。
git clone https://github.com/cp2k/cp2k.git
cd cp2k/
もし最新GPU対応させたい場合、「余計な事」の節で書いたようにここで Makefileなどを編集していますが、これは最適化にこだわりがなければ必要ないので、何をどうしたかは最後のおまけに回します。
最初にビルドオプションと依存パッケージの準備である install_cp2k_toolchain.sh
を実行します。このコマンドでCP2Kに必要なパッケージの確認・ビルドをして、適宜Makefileを作ってくれます。
これは基本的にはCP2Kのドキュメントに従えばいいのですが、 fftw
などは準備の節で触れたようにGromacsからも同じものを使いたいため、そういったものは system のものを指定するようにします。
cd tools/toolchain
./install_cp2k_toolchain.sh --with-gcc=system --with-libxsmm=install --with-openblas=system --with-fftw=system --with-openmpi=system --enable-cuda
GPU最適化オプションを付けたい場合、自分のGPUの型番からコードを調べて、 --gpu-ver=A40
みたいな感じで install_cp2k_toolchain.sh
を追加してやればいいです。
いくつかビルドするものがあると思われますので、少々時間がかかります。終わり次第、生成されたMakefileの設定ファイルを所定の場所にコピー、環境変数を準備し、元の場所に戻ります。
cp toolchain/install/arch/* ../arch
source toolchain/install/setup
cd ..
CPU版ビルド
まず、CPU版である local.ssmp
と local.psmp
をビルドします。
make -j 28 ARCH=local VERSION="ssmp psmp"
ここで、このままだとなぜかFortranのオプションがよくなくてビルド中に Unused dummy argument みたいなエラーが出るかもしれません。そのときは以下のファイルを編集してやります。
vi arch/local.ssmp
vi arch/local.psmp
これらのファイル中に WFLAGS
を定義している行がありますが、これから -Werror=unused-dummy-argument
を削除します。
まあ、今回ビルドしたコミットからこの記事を書くまでの数日のあいだにいくつもコミットがありますので、この記事を基にビルドするころには修正されて、このエラー対応はいらなくなってるかもしれません。
make
コマンドが上手くいけば、バイナリが exe/local/
ディレクトリ中にできていると思います。
CPU版をGromacsにリンクするなら、以下のようにCP2Kのライブラリを作ります。
make -j 28 ARCH=local VERSION="ssmp psmp" libcp2k
これにより、 lib/local/ssmp
と lib/local/psmp
ディレクトリ中に libcp2k.a
が生成されています。普通のバイナリのビルドでも各モジュールのライブラリ (libcp2kao.a
など)がすでにできているのですが、GROMACSから必要な libcp2k.a
はこのコマンドで改めて作ってやる必要があります。
GPU版ビルド
こちらも同様に make
コマンドを実行するだけです。
なお、なぜか psmp
はリンク時に elpa_constants.mod
が見つからないといわれ失敗しました。まあGPU使うときはCPUが並列でなくてもいいかなという気分になることが多いので今回はあきらめます。
どうもSIRIUSで使うらしいです。
make -j 28 ARCH=local_cuda VERSION="ssmp"
make -j 28 ARCH=local_cuda VERSION="ssmp" libcp2k # gromacsリンク用
また、こちらも同様にFortranの unused-dummy-argument
エラーが出るかもしれません。そのときは arch/local_cuda.ssmp
を修正しましょう。
最後のほうで ld: cannot find -lcuda
とか言われたら、以下のようにパスをとおしてやります。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib64/stubs
これでビルドはできる、と思います。
テスト
ちゃんと計算できるバイナリができたかチェックします。まず、CPU版のほうは
make -j 28 ARCH=local VERSION="ssmp psmp" test > test_local_ssmp_psmp.log
でテスト用プログラムがビルド、実行されます。最後の > test_local_ssmp_psmp.log
はその結果を保存しておくためのリダイレクトです。
また、CUDAのほうも同様に
make -j 28 ARCH=local_cuda VERSION="ssmp" test
でできます。
なお、自分の環境ではCPU版のほうは問題なく通りましたが、CUDA版のほうが50程度RUNTIME ERRORとかTIMEOUTしていました。面倒なのでまだやってないですがちょっと内容を精査する必要がありそうです。
(テスト実行はドキュメントを特にみておらず、make test
か make tests
だろうと適当にやってみたらなんかテスト始めたからそれで良しとしました)
インストール
残念ながら make install
はないので、出来上がった実行ファイルを自力で移動します。
mv exe/ /path/to/cp2k/root/dir
リンク用ライブラリは lib/local_cuda/ssmp
などの中に生成されています。
これもインストール先のディレクトリに入れてもいいですが、今回はcp2kのビルド現場に置きっぱなしにして、GROMACSのCmakeの設定でそこを見に行くことにします。
Gromacs ビルド
こちらも Gromacsの ビルドドキュメント Installation guide - GROMACS 2025.2 documentation にある通りです。Cmakeの設定で以下のようにしました。
あ、ウチはCMakeはとりあえず cmake-gui
を使っていて、あまりコマンドラインオプションで指定する習慣がありません。
-
cp2k_dir
:/path/to/src/cp2k/lib/local/ssmp
-
DBUILD_SHARED_LIBS
:OFF
-
DGMXAPI
:OFF
-
DGMX_INSTALL_NBLIB_API
:OFF
-
DGMX_DOUBLE
:ON
FFTWのリンクなどは、CP2Kの方でsystem(つまりapt)のものを使うようにしたので、 CMakeが自動的に拾ってくれるやつで大丈夫です。
また、今回はシングルプロセス版CP2Kを用いましたが、ほかのバージョンがよければそれに対応する libcp2k.a
を含むパスを cp2k_dir
で指定します。 たとえばマルチプロセス版がよければ cp2k_dir
で /path/to/src/cp2k/lib/local/psmp
を、GPU版としたい場合は /path/to/src/cp2k/lib/local_cuda/ssmp
とすればよいです。
あとはMakefileが生成されたら make
→ make install
としましょう。 DGMX_DOUBLE
が ON
になっているので、バイナリは gmx_d
となります。
普通のGPU版のバイナリが gmx
であれば、同じインストールディレクトリで同居できます。 同じ source GMXRC.sh
で gmx
としたらGPU版を、 gmx_d
としたらQM/MM用倍精度版を呼び出せます。
これでCP2Kを呼び出せるGromacsができました。
おまけ:Blackwell対応編集
Githubからクローンしてきた cp2k
ディレクトリに入って、 tools/toolchain/install_cp2k_toolchain.sh
と exts/build_dbcsr/Makefile
を編集します。以下、編集後の git diff
の出力です。
--- a/exts/build_dbcsr/Makefile
+++ b/exts/build_dbcsr/Makefile
@@ -93,6 +93,8 @@ else ifeq ($(GPUVER),A40)
override GPUVER := A100
else ifeq ($(GPUVER),H100)
ARCH_NUMBER = 90
+else ifeq ($(GPUVER),B40)
+ ARCH_NUMBER = 100
else ifeq ($(GPUVER),Mi50)
ARCH_NUMBER = gfx906
else ifeq ($(GPUVER),Mi100)```
--- a/tools/toolchain/install_cp2k_toolchain.sh
+++ b/tools/toolchain/install_cp2k_toolchain.sh
@@ -495,7 +495,7 @@ while [ $# -ge 1 ]; do
--gpu-ver=*)
user_input="${1#*=}"
case "${user_input}" in
- K20X | K40 | K80 | P100 | V100 | A100 | H100 | A40 | Mi50 | Mi100 | Mi250 | no)
+ K20X | K40 | K80 | P100 | V100 | A100 | H100 | A40 | Mi50 | Mi100 | Mi250 | B40 | no)
export GPUVER="${user_input}"
;;
*)
@@ -1011,6 +1011,9 @@ case ${GPUVER} in
H100)
export ARCH_NUM="90"
;;
+ B40)
+ export ARCH_NUM="100"
+ ;;
Mi50)
# TODO: export ARCH_NUM=
;;
これで、 install_cp2k_toolchain.sh
に --gpu-ver=B40
を指定してやればBlackwell対応コードでコンパイルできるかと思います。
最後に
ちゃんとビルドできたことを確認するため、 GromacsのQMMMチュートリアルを動かしてみます。
その様子をこちらの記事に書きました。
Discussion