👷

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 は未対応です。とはいえ nvcccompute_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.ssmplocal.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/ssmplib/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 testmake 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が生成されたら makemake install としましょう。 DGMX_DOUBLEON になっているので、バイナリは gmx_d となります。
普通のGPU版のバイナリが gmx であれば、同じインストールディレクトリで同居できます。 同じ source GMXRC.shgmx としたらGPU版を、 gmx_d としたらQM/MM用倍精度版を呼び出せます。

これでCP2Kを呼び出せるGromacsができました。

おまけ:Blackwell対応編集

Githubからクローンしてきた cp2k ディレクトリに入って、 tools/toolchain/install_cp2k_toolchain.shexts/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