インテル® MPI ライブラリーを利用した Python* の並列プログラミング

同カテゴリーの次の記事

インテル® Distribution for Python* の紹介

この記事は、インテルの The Parallel Universe Magazine 25 号に収録されている、インテル® MPI ライブラリーを利用して Python* 並列プログラミングのパフォーマンスを向上する方法に関する章を抜粋翻訳したものです。

ハイパフォーマンス・コンピューティング (HPC) はこれまで、Fortran や C のようなコンパイラー型言語を利用してソフトウェア開発が行われてきました。ところが最近では、Python* のようなインタープリター型高水準言語でも、モジュールを利用して、モデリング、シミュレーション、設計などの科学/エンジニアリング・アプリケーションを簡単に開発できるようになりました。では、Python* で並列アプリケーションを作成することは可能なのでしょうか。

この記事では、分散メモリーシステムの HPC で最もよく使用されているプログラミング・モデルである、メッセージ・パッシング・インターフェイス (MPI) と Python* を組み合わせた並列プログラミングの方法について説明します。スクリプト言語と MPI 間のインターフェイスでよく発生する問題は、パフォーマンスに関するものです。

まず、ネイティブ MPI 実装 (インテル® MPI ライブラリー) の Python* ラッパーとして mpi4py を使用する、並列 Python* アプリケーションの開発ガイドラインを説明します。mpi4py は、インテル® Distribution for Python* (2017 以降) に含まれています。さらに、mpi4py を使用して記述した MPI アプリケーションのパフォーマンス向上に役立つ手法と、インテル® Trace Analyzer & Collector のようなインテルのツールを使用して並列 Python* アプリケーションを解析する方法について説明します。

MPI for Python*

MPI for Python* (mpi4py) は、MPI にオブジェクト指向のアプローチを提供します。このインターフェイスは、標準 C++ MPI バインドの MPI 構文とセマンティクスを Python* に変換するように設計されています。

一般に、mpi4py は、Python* オブジェクトのシリアル化機能を使用して、任意のビルトインまたはユーザー定義の Python* オブジェクトと通信します。特に大きなバッファーを転送する場合、シリアル化によりメモリーやプロセッサーの利用に著しいオーバーヘッドが発生します。幸い、mpi4py は、一部の型 (文字列や数値配列など) で提供される標準 Python* メカニズムを備えたオブジェクトの直接通信をサポートしています。この機能は、C 側で、関連データを含む連続するメモリーバッファーへのアクセス (アドレスと長さ) を提供します。この機能を、複雑なメモリーレイアウトを記述するユーザー定義の MPI データ型を構築する機能とともに利用すると、オーバーヘッドを気にすることなく多次元数値配列を含む多くのアルゴリズムを Python* で直接実装して、コンパイルした Fortran、C、C++ コードとほぼ同じ速度で実行することができます。

使用法

図 1 は、mpi4py で記述された簡単な “Hello World” の例です。

from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
name = MPI.Get_processor_name()
if rank == 0:
    print "Hello world: rank %d of %d running on %s" % (rank, size, name)
    for i in xrange(1, size):
        rank, size, name = comm.recv(source=i, tag=1)
        print "Hello world: rank %d of %d running on %s" % (rank, size, name)
else:
    comm.send((rank, size, name), dest=0, tag=1)

図 1 サンプル・アプリケーション

この例で、comm はコミュニケーター・オブジェクトです。MPI 関数 Get_size()、Get_rank()、send()、recv() は、このコミュニケーター・オブジェクトのメソッドです。

図 1 の例は図 2 のコマンドを使用して実行します。

$ source <intel_mpi>/bin/mpivars.sh

$ source <intel_python>/bin/pythonvars.sh

$ mpirun -ppn 1 -n 2 -hosts node01,node02 python
helloworld.py
Hello world: rank 0 of 2 running on node01
Hello world: rank 1 of 2 running on node02

図 2 コマンド

mpivars.sh スクリプトは、インテル® MPI ライブラリーの環境を設定します。pythonvars.sh は、インテル® Distribution for Python* の環境変数を設定します。mpirun ユーティリティーは、MPI アプリケーションを起動します。

関連記事