0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ubuntu 22.04 + Conda環境でGPAWをマルチCPU&GPU(NVIDIA L4)対応でビルドする際に出会った罠と解決策まとめ

0
Posted at

はじめに

化学計算プログラムである GPAW を、マルチCPU(MPI並列)およびGPU(NVIDIA CUDA)の両方を利用できるようにソースからビルドしました。

JupyterHub環境やConda仮想環境の組み合わせでは、ホストシステムとのコンパイラ競合や環境変数の遮断、CUDAのバージョン不整合など、信じられないほどの数の罠(エラー)に直面しました。これらを一つずつ突破した完全な手順を、トラブルシューティングの記録とともに残します。

動作環境

  • OS: Ubuntu 22.04
  • GPU: NVIDIA L4 (Ada Lovelaceアーキテクチャ / sm_89)
  • Python: 3.14.5 (Conda仮想環境)
  • 主要ライブラリ: GPAW 25.7.1b1, CuPy 14.1.1, ASE 3.28.0

1. Conda環境の整備(依存関係の統一)

システムのコンパイラ(/usr/bin/gccmpicc)とConda環境内のライブラリが混ざるとリンクエラーの原因になります。まずはコンパイラ、MPI、並列線形計算ライブラリをすべてConda環境内に統一します。

# 1. 基本的なライブラリとConda用コンパイラセット(GCC 13に固定)を導入
# ※ 最新のGCC 14を入れるとCUDA(nvcc)が「サポート外」とエラーを吐くため、バージョン13に固定するのがミソです。
conda install -c conda-forge "gcc_linux-64=13" "gxx_linux-64=13" openmpi scalapack fftw libxc

# 2. Conda環境内にCUDA開発環境を導入
conda install -c nvidia cuda-nvcc cuda-toolkit

さらに、Python用の必須パッケージを導入します。

pip install numpy scipy matplotlib ase cupy


2. siteconfig.py の作成

GPAWのビルド設定を制御する siteconfig.py を、GPAWのソースディレクトリ直下に作成します。
NVIDIA L4で駆動させるため、アーキテクチャに sm_89 を含めること、およびConda環境のパスを明示的に通すことがポイントです。

# siteconfig.py
import os

compiler = 'gcc'
mpicompiler = 'mpicc'
mpilinker = 'mpicc'

# 依存ライブラリの指定
libraries = ['xc', 'fftw3', 'blas', 'lapack', 'scalapack']
scalapack = True

# GPU (CUDA) 設定の有効化
gpu = True
gpu_target = 'cuda'
gpu_compiler = 'nvcc'

# NVIDIA L4 (sm_89) を含む、主要なGPUアーキテクチャを網羅するファットバイナリ設定
gpu_compile_args = [
    '-O3', '-g',
    '-gencode', 'arch=compute_70,code=sm_70', # V100
    '-gencode', 'arch=compute_75,code=sm_75', # T4
    '-gencode', 'arch=compute_80,code=sm_80', # A100
    '-gencode', 'arch=compute_86,code=sm_86', # RTX 3000系 / A10G
    '-gencode', 'arch=compute_89,code=sm_89', # RTX 4000系 / L4
    '-gencode', 'arch=compute_90,code=sm_90'  # H100
]
libraries += ['cudart', 'cublas']

# Conda環境内の include / lib パスを強制的に読み込ませる
conda_env = os.environ.get('CONDA_PREFIX')
if conda_env:
    include_dirs += [os.path.join(conda_env, 'include')]
    library_dirs += [os.path.join(conda_env, 'lib')]
    runtime_library_dirs += [os.path.join(conda_env, 'lib')]
    
    # CondaのCUDA Toolkit特有のディープな階層もカバー
    cuda_target_inc = os.path.join(conda_env, 'targets/x86_64-linux/include')
    cuda_target_lib = os.path.join(conda_env, 'targets/x86_64-linux/lib')
    if os.path.exists(cuda_target_inc):
        include_dirs += [cuda_target_inc]
        library_dirs += [cuda_target_lib]
        runtime_library_dirs += [cuda_target_lib]


3. GPAWのコンパイルとインストール

設定ファイルを配置したら、一度ソースツリーをクリーンにしてからインストール(Editableモード)を実行します。

git clean -dfx
pip install -e . -v

-v を付けておくことで、nvccmpicc が意図したフラグでビルドされているかリアルタイムに監視できます。

ビルド完了後、ポテンシャルデータをインポートします。

gpaw install-data <任意の展開先ディレクトリ>

状態確認

gpaw info

出力の MPI enabled: yesGPU enabled: yesscalapack: yes になっていることを確認します。


4. 実行時の罠と解決策

罠①:計算開始時に RuntimeError: Failed to find CUDA headers.

GPAWのC拡張ビルドは通っても、いざPythonで実行するとCuPyがJITコンパイル時に「CUDAのヘッダ(cuda.h)が見つからない」とマヌケなエラーを吐きます。Conda環境の深すぎる階層にヘッダが隠されているのが原因です。

【解決策】
Pythonパッケージとして公式のランタイムヘッダを直接流し込むことで、環境変数の呪縛から解放されます。

pip install nvidia-cuda-runtime-cu12

罠②:mpirun -np 2 で並列実行すると Segmentation fault (Signal 11)

1コア+1GPUだと正常に動くのに、マルチCPU(MPI)にした瞬間、MPI_Allreduce 内の mca_coll_cuda_allreduce でセグフォが起きました。これはConda版OpenMPIの「GPU-aware MPI(GPUメモリ間直接通信)」の不整合によるものです。

【解決策】
実行時に環境変数 GPAW_NO_GPU_MPI=1 を指定し、安全なCPUメモリ経由の通信へとフォールバックさせます。


5. 最終的な動作確認スクリプト

JupyterLabのノートブックや、ターミナルから以下の並列実行スクリプトを走らせます。

# gpaw_parallel.py
import time
from ase.build import bulk
from gpaw import GPAW, PW
from gpaw.mpi import world

# テスト用のシリコンバルク構造
atoms = bulk('Si', 'diamond', a=5.43)

calc = GPAW(
    mode=PW(ecut=350),
    xc='PBE',
    kpts=(6, 6, 6),
    parallel={'gpu': True}, # 全MPIプロセスでGPUを利用
    txt='gpaw_mpi.txt' if world.rank == 0 else None
)
atoms.calc = calc

if world.rank == 0:
    print(f"--- 計算開始 (MPIプロセス数: {world.size}) ---")
    start = time.time()

energy = atoms.get_potential_energy()

if world.rank == 0:
    print(f"計算終了! 所要時間: {time.time() - start:.2f}")
    print(f"シリコンの全エネルギー: {energy:.6f} eV")

実行コマンド(4並列の例)

GPAW_NO_GPU_MPI=1 mpirun -np 4 python gpaw_parallel.py

これで、NVIDIA L4 GPUの圧倒的な恩恵を受けつつ、マルチCPUでタスクを分散した高速な量子化学計算ができるようになります!同じような環境変数の迷宮で困っている方の参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?