MPIビルドのfistr1でBLASが参照実装に結びつき、benchmarkがfailし続けている

概要

master の 0d6b3dff(!674 (merged) のマージ)以降、MPI を含むビルド(mpi、hybrid)の benchmark で 15_eigen_spring と 19_conrod が critical になり、master とその上に載るブランチの pipeline が fail し続けています。!677 (merged) のように性能に関係しない MR の pipeline も fail します。

原因は、MPI ビルドの fistr1 で BLAS の結びつき先が MKL から参照実装(libblas.so.3)に替わったことです。!674 (merged) で加わった hecmw_mf_kernel.F90 が dgemm などを直接呼ぶため、Trilinos が持ち込む汎用の libblas.so が、MKL より前の直接の依存として実行ファイルに記録されるようになりました。実行時のシンボル解決はこの並び順で行われるので、MUMPS、ML、ScaLAPACK の BLAS 呼び出しもすべて参照実装に向きます。

遅くなる2例題はどちらも MUMPS を通ります(eigen は SOLVER=MUMPS、conrod は ML の粗格子ソルバ)。DIRECTmf を実行しなくても遅くなります。serial、openmp ビルドは Trilinos をリンクしないので影響を受けません。

実測

master の 1072641a の pipeline(2911035281)。baseline(v5.9)→ current、中央値、秒。

ビルド/実行 15_eigen_spring 19_conrod
serial/serial 23.2 → 15.3(-34%) 87.0 → 89.7(+3%)
mpi/mpi 13.7 → 23.1(+69%、critical) 8.2 → 13.3(+63%、critical)

マージ直前の e01d768c では、mpi/mpi も eigen 18.9 → 12.5(-34%)、conrod 12.5 → 12.6(+0%)でした。

結びつき先の確認

benchmark ジョブに readelf、ldd、LD_DEBUG=bindings の出力を足しただけのブランチ ci/diagnose-blas-binding(コミット 1d6bee54、master の 1072641a から分岐)を fork で走らせました。 https://gitlab.com/chikasuiro/FrontISTR/-/pipelines/2911157727

mpi ビルドの fistr1 での結びつき先です。fork のジョブログには保存期限があるので、結果を写しておきます。

呼び出し元 シンボル baseline(v5.9) current(1072641a)
libdmumps-5.6.so dgemm_、dgemv_、dtrsm_ libmkl_gf_lp64.so libblas.so.3
libtrilinos_ml.so.13.2 dgemm_、dgemv_ libmkl_gf_lp64.so libblas.so.3
libmkl_scalapack_lp64.so dgemm_、dtrsm_ ほか libmkl_gf_lp64.so libblas.so.3
fistr1 本体 dgemm_、dgemv_、dtrsm_ (参照なし) libblas.so.3

current では、実行ファイルの直接の依存に libblas.so.3 が libdmumps と MKL より前に加わっています。libblas.so.3 の実体は /usr/lib/x86_64-linux-gnu/blas/libblas.so.3(参照実装)です。serial ビルドでは baseline、current とも MKL に結びつき、差はありません。

fork の pipeline では fail にならない点

上の診断用 pipeline は success ですが、benchmark 9件中6件で critical が出ています(mpi、hybrid ビルドの全ジョブ)。fail 条件の BENCHMARK_FAIL_ON_REGRESSION は本家プロジェクトの CI/CD 変数にだけ設定されており、fork には引き継がれず既定値 0 で動くため、success に見えるだけです。本家と同じ設定なら fail します。

!674 (merged) のブランチの pipeline(fork)でも、9/25 から同じ critical が出ていましたが、同じ理由で success になっており、マージ後の本家の pipeline で初めて fail しました。