並列I/OとHDF5

計算は速いのに書き出しで詰まる。MPI-IOの集団I/OとHDF5並列書き込み、Lustreのストライピングを原理から押さえれば、I/O律速を設計段階でほどけます。

応用HPC並列I/OHDF5MPI-IOLustreチェックポイント最終更新: 2026-07-29
3つの要点
TL;DR
  1. MPI-IOの集団I/O(two-phase I/O)は多数の小さな飛び飛び書き込みを、少数の集約プロセスがまとめてストライプ幅の大きな連続書き込みに変換する仕組みで、独立I/Oより桁で速くなることがある。
  2. HDF5/PnetCDFはMPI-IOの上に自己記述フォーマットを載せた層で、並列書き込み時は全プロセスが同じメタデータ更新に集団参加する必要があり、これを怠ると破損やハングを招く。
  3. Lustre/GPFSではストライプカウントとストライプサイズがOSTへの分散を決め、MPI-IOの集約プロセス数をストライプ数に合わせると帯域を使い切れる。

I/Oが律速になる構造 ── なぜ計算より書き出しが遅いのか

大規模シミュレーションでは、計算ノードの演算性能が伸び続ける一方、状態やチェックポイントを永続化するストレージ帯域はそれに追いつきません。数万プロセスが一斉に配列を書き出すと、律速は演算ではなくI/Oに移ります。並列I/Oの設計とは、この帯域とメタデータ処理という有限資源を、どうすれば連続した大きなアクセスに変換して使い切れるかという問題です。

横にスクロール

並列I/OとHDF5について、問題分割から計算、通信、集約、性能限界までを示す図
並列処理の実行経路と、性能・精度・通信のトレードオフを整理します。

素朴な実装は2通りあります。1つは各プロセスが自分専用ファイルを持つN-to-N(file-per-process)。もう1つは全プロセスが1つの共有ファイルの別々の領域を書くN-to-1(shared-file)です。N-to-Nはファイル数がプロセス数まで膨れ、メタデータサーバーへの create/open が殺到してリスタート時のファイル列挙も遅くなります。N-to-1はファイル1個で済みますが、各プロセスの担当領域が論理的に飛び飛び(strided)で、素朴に書くと小さなアクセスが分散して帯域が出ません。ここを橋渡しするのがMPI-IOの集団I/Oです。

独立I/Oと集団I/Oの違い

MPI-IOには2系統の書き込みがあります。MPI_File_write_at(独立I/O)は各プロセスが単独でファイルへ書き、他プロセスと協調しません。MPI_File_write_at_all(集団I/O、末尾の _all)は同じコミュニケータの全プロセスが参加して初めて完了する集団操作で、この参加を前提に実装がアクセスを再編できます。両者はAPIとしては似ていますが、内部で走るアルゴリズムがまったく異なります。

集団I/Oの核心 ── two-phase I/O

集団I/Oの代表実装がtwo-phase I/O(ROMIO実装の中核)です。各プロセスの書きたい領域がファイル上で飛び飛びでも、集団全体で見ればファイルのある区間を密に覆っていることに着目します。処理は名前の通り2フェーズです。

two-phase I/O(書き込みの場合)

フェーズ1: 通信フェーズ(redistribution)
  少数の「集約プロセス(aggregator)」を選ぶ
  ファイルを連続した領域(file domain)に分割し各集約プロセスへ割り当てる
  全プロセスは自分のデータを、担当する集約プロセスへMPIで送る
  → 集約プロセスのメモリ上に、ファイルオフセット順の連続バッファが組み上がる

フェーズ2: I/Oフェーズ
  各集約プロセスが、連続バッファをストライプ幅の大きな1回の書き込みで出す
  → ファイルシステムには「大きく連続したアクセス」だけが届く

要は、飛び飛びで小さいアクセスの集合を、ネットワーク上の再配置(redistribution)によって少数の連続した大アクセスへ組み替えます。ネットワーク帯域はストレージ帯域より広いことが多いため、この付け替えは割に合います。この再配置はMPIの集団通信と同じ発想で、全プロセス参加を前提に通信パターンを最適化している点が独立I/Oとの決定的な差です。

集団I/Oが効く条件・効かない条件

two-phase I/Oが有利なのは、各プロセスのアクセスが小さく飛び飛びで、集団全体ではファイルを密に覆う場合です。逆に、各プロセスが最初から巨大で連続した領域を書くなら、再配置は純粋なオーバーヘッドで、独立I/Oのほうが速いことがあります。MPI-IOヒント romio_cb_write = enable/disable/automatic で集団バッファリングを制御でき、automatic は実装がアクセスパターンから判定します。

HDF5とNetCDF ── フォーマット層とMPI-IOの関係

MPI-IOはバイト列の並列アクセスを提供しますが、「配列の形・型・単位」といった意味は持ちません。ここを埋めるのがHDF5やNetCDFなどの自己記述フォーマットです。これらはファイル内にデータ本体と、それを解釈するメタデータ(次元・データ型・属性)を一緒に格納します。重要なのは、並列HDF5(PHDF5)やPnetCDFがMPI-IOの上に載る層であり、実際のバイト書き込みは下位のMPI-IOへ委譲する点です。

役割並列書き込み時の要点
HDF5 / PnetCDF配列・型・属性を持つ自己記述フォーマットメタデータ更新は全プロセス集団で行う必要がある
MPI-IO(ROMIO)共有ファイルへの並列バイトアクセスと集団I/Otwo-phase I/Oでストライプ単位の連続アクセスへ再編
並列ファイルシステムLustre / GPFS などの物理ストレージストライピングでOST群へデータを分散配置

並列書き込みで最も事故が多いのがメタデータの扱いです。HDF5でデータセットを作成・拡張する操作(H5Dcreate、サイズ変更など)はファイル構造そのものを書き換えるため、全プロセスが同一の呼び出しに集団参加しなければなりません。一部プロセスだけが異なるデータセットを作る、あるいは片方だけがサイズ変更すると、各プロセスが持つファイル構造の認識がずれ、破損やデッドロックに直結します。データ本体の書き込みは各プロセスが別領域を担えますが、メタデータは全員で足並みを揃える、という非対称性が並列フォーマット層の鉄則です。

集団メタデータ操作を独立で呼ぶとハング・破損する

PHDF5では、データセット生成・削除・次元拡張・属性作成といった構造変更は集団(collective)操作です。if (rank == 0) の分岐内だけで H5Dcreate を呼ぶ、といったコードは典型的な事故原因で、全プロセスが到達しない集団呼び出しはMPIバリアで永久待機(ハング)するか、メタデータの不整合でファイルを壊します。データ転送だけは独立(H5FD_MPIO_INDEPENDENT)と集団(H5FD_MPIO_COLLECTIVE)を選べますが、構造変更に選択肢はありません。

ストライピングとLustre/GPFS

並列I/Oの帯域は、最終的にファイルがどうストレージへ分散されるかで決まります。Lustreでは、1つのファイルは複数のOST(Object Storage Target、実体はディスク群)に分割配置されます。これを制御する主パラメータが2つあります。

  • ストライプカウント(stripe count): そのファイルを何台のOSTに分散させるか。カウントが大きいほど並列にアクセスできるディスクが増え、集約帯域が上がる。
  • ストライプサイズ(stripe size): 1つのOSTへ連続して書くブロックの大きさ。このサイズ単位でOSTをラウンドロビンに巡回する。
ストライピングの巡回(stripe count = 4 の例)

  ファイルの論理オフセット →
  [ stripe0 ][ stripe1 ][ stripe2 ][ stripe3 ][ stripe0 ][ stripe1 ]...
      OST0       OST1       OST2       OST3       OST0       OST1

  1本のOSTだけに全部載せる(count=1)と、そのOSTの帯域が上限になる
  count=4なら理想的には4台分の帯域を合算できる

ここでMPI-IOの集団I/Oとストライピングが噛み合います。two-phase I/Oの集約プロセス数をストライプカウントに合わせ、各集約プロセスの書き込み単位をストライプサイズの整数倍にそろえると、1回の書き込みが1台のOSTに連続して落ち、OST間の競合(同じOSTを複数プロセスが奪い合うロック競合)を避けられます。ROMIOのLustre向けドライバは、ヒント striping_factor(=stripe count)や cb_nodes(集約ノード数)を通じてこの整合を取ります。GPFS(IBM Storage Scale)も同様にブロックサイズ単位でのアクセス整合が帯域を左右し、思想は共通です。

デフォルトのストライプ設定は往々にして狭すぎる

多くのLustre環境の既定ストライプカウントは1〜2で、単一の巨大ファイルを数千プロセスで共有すると、少数のOSTに全負荷が集中して帯域が頭打ちになります。lfs setstripe -c <count> -S <size> を書き込み先ディレクトリへ事前設定し、共有ファイルのサイズと集約プロセス数に見合うカウントへ広げるのが定石です。逆にファイルが小さいのにカウントを過大にすると、OSTあたりのアクセスが細切れになりメタデータ・接続オーバーヘッドが増えます。

I/Oボトルネックとチェックポイント設計

I/Oが律速かどうかは、Rooflineモデルと同じ発想で、供給可能なストレージ帯域と要求データ量の比から見積もれます。1ステップで書き出すデータ量をD、達成可能な集約帯域をBとすれば、書き込み時間はおよそ D/B で下限が決まり、これが計算時間より長ければ純然たるI/O律速です。ここを改善する主軸は「アクセスを連続化して実効帯域Bを上げる(集団I/O+ストライピング整合)」と「書き出すDを減らす(圧縮・間引き)」の2方向になります。

チェックポイントはこの並列I/Oが最も重くのしかかる場面です。チェックポイント・リスタートの実効オーバーヘッドは、まさにここで論じた集団I/Oとストライピングの整合で決まります。書き込み中も計算を止めない非同期化や、ノードローカルNVMeを一次受けにする多階層化と組み合わせると、実効的な書き込み時間をさらに隠蔽できます。エクサスケール規模ではノード数に反比例して障害間隔が縮むため、チェックポイント頻度が上がり、並列I/Oの効率がシステム全体の稼働率を直接左右する一級の設計課題になります。

まとめ

  • I/O律速の本質は、多数プロセスの小さく飛び飛びなアクセスを、いかに連続した大アクセスへ変換してストレージ帯域を使い切るかにある。
  • MPI-IOの集団I/O(two-phase I/O)は、通信フェーズで少数の集約プロセスへデータを再配置し、I/Oフェーズでストライプ単位の連続書き込みに変えることで独立I/Oを大きく上回ることがある。
  • HDF5/PnetCDFはMPI-IOの上の自己記述フォーマット層で、データ転送は独立/集団を選べるが、データセット生成や次元拡張といったメタデータ更新は必ず全プロセス集団で行う必要がある。
  • Lustre/GPFSではストライプカウント・ストライプサイズがOSTへの分散を決め、集約プロセス数とストライプ数、書き込み単位とストライプサイズをそろえると帯域を最大化できる。この整合がチェックポイントの実効オーバーヘッドと大規模系の稼働率を左右する。

HPC・科学技術計算の記事ガイド

並列I/OとHDF5を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

HPC

比較で見る軸

難易度: advanced / カテゴリ: HPC・科学技術計算 / タグ数: 6

導入後に効く点

HDF5/PnetCDFはMPI-IOの上に自己記述フォーマットを載せた層で、並列書き込み時は全プロセスが同じメタデータ更新に集団参加する必要があり、これを怠ると破損やハングを招く。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
HPC・科学技術計算
タグ数
6

判断チェックリスト

  • 自社の用途が「HPC / 並列I/O」に近いか確認する。
  • 強みである「MPI-IOの集団I/O(two-phase I/O)は多数の小さな飛び飛び書き込みを、少数の集約プロセスがまとめてストライプ幅の大きな連続書き込みに変換する仕組みで、独立I/Oより桁で速くなることがある。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

HPC並列I/OHDF5MPI-IOLustre