パフォーマンス計測の改善自動化フレームワークPIRA は、Score-P を使用する際に、未知のコード ベースに対して合理的なパフォーマンス計測値を生成するという時間のかかるタスクに取り組みます。詳細については、次の論文を参照してください。
[PI18] | ヤン=パトリック・レール、アレクサンダー・ヒュック、クリスチャン・ビショフ。 PIRA: パフォーマンス計測の改良自動化。 「第 5 回 ACM SIGPLAN International Workshop on Artificial Intelligence and Empirical Methods for Software Engineering and Parallel Computing Systems (AI-SEPS)」 、1 ~ 10 ページ、ACM、2018 年。 |
[PI19] | ジャン=パトリック・レール、アレクサンドル・カロトイウ、クリスチャン・ビショフ、フェリックス・ウルフ。経験的パフォーマンスモデリングのための自動計測改良。プログラミングおよびパフォーマンス視覚化ツール (ProTools) に関する国際ワークショップ、40 ~ 47 ページ、IEEE、2019 年。 |
[PI21] | ピーター・アルツト、ヤニック・フィシュラー、ヤン=パトリック・レール、クリスチャン・ビショフ。 MPI アプリケーションにおける低オーバーヘッドの負荷不均衡の自動検出。 Euro-Par 2021: 並列処理。コンピューターサイエンスの講義ノート、vol 12820、19 ~ 34 ページ、Springer、2021 年。 |
PIRA は次の 4 つのフェーズを実行します (2 ~ 4 が反復されます)。
PIRA は、自動生成されたラッパーによる MPI 関数の実行時フィルタリングを含む、関数のコンパイル時フィルタリングと実行時フィルタリングの両方をサポートします。コンパイル時フィルタリングでは、必要な関数のみがコンパイル時にインストルメントされ、全体的な測定への影響が大幅に軽減されます。対照的に、実行時フィルタリングでは、コンパイラはターゲット アプリケーションのすべての関数にインストルメンテーション フックを挿入し、フィルタリングは実行時に行われます。
PIRA には、CMake (>=3.16)、Clang/LLVM 10、Python 3、Qt5、OpenMPI 4 が必要です。PIRA (または MetaCG) はさらにダウンロード (およびビルド) されます。
インターネットにアクセスできない環境で PIRA をビルドする場合は、 resources/build_submodules.sh
スクリプトを参照して、ニーズに合わせて調整してください。
PIRA リポジトリのクローンを作成します。
$> git clone https://github.com/tudasc/pira
$> cd pira
次に、提供されたスクリプトを使用して依存サブモジュールをビルドするか、さまざまなオプションの値を渡します (使用可能なオプションについては、 -h
による使用法情報を参照してください)。ダウンロードおよびビルドされたすべてのファイルはexternal/src/
に配置され、すべてのインストールはexternal/install/
に配置されます。 PIRA の外部のコンパイルのために生成されるコンパイル プロセスの数を指定します。このスクリプトは、PIRA の依存関係をデフォルト バージョンでダウンロードします。これらのバージョンは CI でもテストされており、動作することが期待されています。
$> cd resources
$> ./build_submodules.sh -p <ncores>
最後のステップとして、ビルド スクリプトはサブモジュールのインストール パスをファイルresources/setup_paths.sh
に書き込みます。 PIRA を再構築したい場合は、このファイルを忘れずにgit restore
ください。
PIRA を構築して試すための (実験用) Dockerfile
提供しています。
$> podman build -t pira:master -f docker/Dockerfile .
統合テストなど、コンテナ内で実行する場合は、次のようにスクリプトを呼び出してください。
$> cd resources
$> . setup_paths.sh
$> cd ../test/integration/GameOfLife # Example test case
# By default PIRA will look into $HOME/.local, which is not currently existent in the docker
# XDG_DATA_HOME signals where to put the profiling data PIRA generates
$> XDG_DATA_HOME=/tmp ./run.sh
PIRA の使用方法の完全な例については、 /test/integration/*
フォルダーにあるrun.sh
スクリプトをチェックアウトしてください。開始点として適しているのは、 GameOfLife
フォルダーとそのテスト ケースです。
まず、 resources
フォルダー内のスクリプトを取得して、必要なパスを設定します。
$> cd resources/
$> . setup_paths.sh
次に、 ./test/integration/GameOfLife
フォルダーにあるrun.sh
スクリプトを使用して、Conway のライフ ゲームの非常に単純な実装で PIRA のサンプル アプリケーションを実行できます。
$> cd ./test/integration/GameOfLife
$> ./run.sh
スクリプトは、最初から必要なすべての手順 (つまり、新しいターゲット コード用にすべてのコンポーネントを準備する) を実行して、最終的に PIRA を呼び出します。後続のセクションでは、手順についてさらに詳しく説明します。手順は次のとおりです。
config
構成ファイルへのパス (必須引数)--config-version [1,2]
PIRA 構成のバージョン。2 がデフォルトであり、推奨されます。 1は廃止されました。--runtime-filter
実行時フィルタリングを使用します。デフォルトは false です。コンパイル時フィルタリングでは、関数はコンパイル時に計測されず、全体的な測定への影響は大幅に軽減されますが、反復ごとにターゲットを再構築する必要があります。対照的に、ランタイム フィルタリングでは、コンパイラはターゲット アプリケーションのすべての関数にインストルメンテーション フックを挿入します。--iterations [number]
Pira の反復回数。デフォルト値は 3 です。--repetitions [number]
測定の繰り返し回数。デフォルト値は 3 です。--tape
(ある程度広範囲にわたる) ログ テープが書き込まれる場所。--extrap-dir
Extra-p フォルダー構造が配置されるベース ディレクトリ。--extrap-prefix
Extra-P プレフィックス。一連の文字である必要があります。--version
PIRA インストールのバージョン番号を出力します。--analysis-parameters
PGIS の分析パラメーターを含む構成ファイルへのパス。 Extra-P モードと LIDe モードの両方に必要です。--slurm-config [path to slurm cfg file]
slurm クラスター上でターゲット コードを実行できるようにします。 slurm 設定ファイルが必要です。詳細については、このセクションを参照してください。 --hybrid-filter-iters [number]
[number] 回の反復後に再コンパイルし、その間にランタイム フィルタリングを使用します。--export
生成された Extra-P モデルとデータ セット サイズをターゲットの IPCG ファイルに添付します。--export-runtime-only
--export
が必要です。すべての繰り返しの実行時間の中央値のみを関数に付加します。エクストラPを使用しない場合のみ使用可能です。--load-imbalance-detection [path to cfg file]
負荷不均衡検出モードを有効にして設定します。詳細については、このセクションをお読みください。 PIRA は、初期インスツルメンテーションを構築し、反復改良中にインスツルメンテーションにどの関数を追加するかを決定するためにソース コード情報を使用します。これは、必要な情報をすべて収集し、その情報を.json
ファイルに出力する Clang ベースのコールグラフ ツールを提供します。 cgcollector
ツールは、サブディレクトリ./extern/src/metacg/cgcollector
にあります。 PIRA では、コールグラフ ファイルがバージョン 2 (MetaCG v2) の MetaCG ファイル形式である必要があります。
CGCollector とそのコンポーネントの詳細については、MetaCG ドキュメントを参照してください。
CGCollector の適用は通常 2 つのステップで行われます。
まず、プロジェクト内のすべてのソース ファイルに対してcgc
が呼び出されます。例えば:
for f in $(find ./src -type f ( -iname "*.c" -o -iname "*.cpp" ) ); do
cgc --metacg-format-version=2 $f
done
ステップ 1 で作成された.ipcg
ファイルは、 cgmerge
使用して一般ファイルにマージされます。
"null"
のみを含む出力ファイルを作成します。 2. プロジェクトに複数のmain
関数が含まれている場合は、ファイルを正しいmain
関数とのみマージしてください。 echo "null" > $IPCG_FILENAME
find ./src -name "*.ipcg" -exec cgmerge $IPCG_FILENAME $IPCG_FILENAME {} +
最終的なグラフは callgraph-analyzer のディレクトリに配置する必要があります。現在 CG 解析にはPGIS を使用しているため、生成されたプログラム ファイル全体を PGIS ディレクトリにコピーします。現時点では、PGIS ディレクトリ内のファイルの名前がパターンitem_flavor.mcg
に従っていることが重要です。項目はターゲット アプリケーションを表します。フレーバーとアイテムという用語については、次のセクションで詳しく説明します。
# Assuming $PIRA holds the top-level PIRA directory
$> cp my-app.mcg $PIRA/extern/install/pgis/bin/item_flavor.mcg
PIRA 構成には、PIRA が自動プロセスを実行するために必要な情報がすべて含まれています。構成ファイルで指定する必要があるさまざまなディレクトリは、絶対パスまたはpira の実行パスを基準とした相対パスのいずれかにすることができます。パスには、 $HOME
などの環境変数が含まれる場合があります。例は、 ./test/integration/GameOfLife
の GameOfLife の例から取得されています。
ユーザーは以下を指定します: 後で定義される項目を検索するディレクトリ。この例では、ディレクトリは./gol/serial_non_template
です。これらのディレクトリには別名が与えられ、「%」記号を使用して逆参照されます。 PIRA の項目は、特定の方法で構築されたターゲット アプリケーションです。これが、この項目がbuildsの下の構成にグループ化される理由です。
{
"builds": {
"%gol": {
"items": {
"gol": {
...
}
}
}
}
"directories": {
"gol": "./gol/serial_non_template"
}
}
すべての項目は、どのアナライザーを使用するかを指定します。デフォルトのアナライザーは PIRA に同梱されており、ソースは./extern/src/metacg/pgis
に、またはインストールは./extern/install/pgis/bin
にそれぞれあります。アナライザーはインスツルメンテーションの改良を管理する責任があるため、PIRA フレームワークの重要な部分です。
argmapフィールドは、パフォーマンス実験の実行時にターゲット アプリケーションに渡されるさまざまな引数を指定します。引数がターゲット アプリケーションにどのように渡されるかは、さまざまなマッパーによって定義されます。この例では、リストに指定された順序でsizeという名前のパラメーターの値を単純に反復する線形マッパーが使用されます。
"argmap": {
"mapper": "Linear",
"size": [50, 80, 110, 150, 300, 500]
}
cubesフィールドは、PIRA が取得した Score-P プロファイルを保存する場所です。その場所にディレクトリ ツリーが構築されるため、PIRA の終了後、ユーザーはそれぞれの場所 (例では/tmp/pira)を渡すだけで Extra-P モデリング ツールを簡単に呼び出すこともできます。
"cubes": "/tmp/pira"
ターゲット アプリケーションはさまざまなフレーバーで構築できるため、フレーバーフィールドにより、さらに別のレベルの区別が追加されます。例としては、ターゲット アプリケーションがリンクする必要があるさまざまな数学ライブラリを指定することが挙げられます。
最後に、ファンクターディレクトリは、PIRA がターゲット アプリケーションの構築、実行、分析方法を最終的に指示するユーザー提供の Python 関数を検索する場所を PIRA に指示します。この例では、PIRA は、構成の場所を基準にしてfunctorsと呼ばれるディレクトリを指します。
"flavors": [
"ct"
],
"functors": "./functors",
"mode": "CT"
このバージョンの PIRA では、モードフィールドは無視されます。
現時点では、ユーザーは 5 つの異なるファンクターを実装する必要があります。
analyze_<ITEM>_<FLAVOR>.py
: アナライザーを呼び出します。clean_<ITEM>_<FLAVOR>.py
: ビルド ディレクトリをクリーンアップします。<ITEM>_<FLAVOR>.py
: インストルメント化されたバージョンをビルドします。no_instr_<ITEM>_<FLAVOR>.py
: バニラバージョンをビルドします。runner_<ITEM>_<FLAVOR>.py
: ターゲット アプリケーションを実行します。ファンクターは通常、アクティブとパッシブの 2 つの呼び出しモードをサポートします。ファンクターは、関数get_method()
によって返されるディクショナリ内のそれぞれの値をTrue
に設定することで、PIRA が使用するモードを通知します。
アクティブ モードでは、ファンクター自体が、ソフトウェアのビルドなどに必要なコマンドを呼び出します。ファンクターが呼び出されると、現在のディレクトリやサブプロセス シェルのインスタンスなどを保持する**kwargs
パラメーターが渡されます。
パッシブ モードは、実行するコマンドのみを返します。たとえば、アイテムの最上位ディレクトリで単純な Makefile を呼び出す文字列make
です。また、CXXFLAGS や追加のリンカー フラグに追加するために必要な事前定義された値など、特定の情報を保持するkwargs
パラメーターも渡されます。受動的ファンクターの例はexamples
とtest
ディレクトリにあります。現在、実装されているすべてのファンクターはパッシブ モードを使用します。
PIRA は、次のキーワード引数をすべてのファンクターに渡します。さらに、さまざまな PIRA コンポーネントが追加の引数を渡す場合があります。
重要: 現在、独自の Score-P バージョンを出荷しています。したがって、PIRA でコンパイル コマンドを調整する必要はなくなりました。さまざまな情報の使用例については、 test/integration/AMG2013
のファンクターを確認してください。
現在、すべてのファンクターに情報は渡されません。
[0]
最初の引数にアクセスし、 [1]
2 番目の引数にアクセスします。.so
ファイルへのパス (MPI フィルタリングに重要)。 一部の分析モードでは追加のパラメーターが必要です。具体的には、PIRA LIDe (以下を参照) および Extra-P モデリング解析にはユーザー指定のパラメーターが必要です。 JSON ファイルを作成し、 --analysis-parameters
-switch を使用してそのパスを PIRA に指定します。次の例には、Extra-P モデリング モードのパラメーターが含まれています。複数の Extra-P モデル (関数が異なるコンテキストで呼び出される場合) を集約するために使用できる戦略は、 FirstModel
、 Sum
、 Average
、 Maximum
です。
{
"Modeling": {
"extrapolationThreshold": 2.1,
"statementThreshold": 200,
"modelAggregationStrategy": "Sum"
}
}
負荷不均衡検出機能の詳細については、[PI21] を参照してください。 --load-imbalance-detection
-parameter を使用して、PIRA 呼び出しに構成ファイルへのパスを指定します。この JSON ファイルは次の構造を持つ必要があります。
{
"metricType": "ImbalancePercentage",
"imbalanceThreshold": 0.05,
"relevanceThreshold": 0.05,
"contextStrategy": "None",
"contextStepCount": 5,
"childRelevanceStrategy": "RelativeToMain",
"childConstantThreshold": 1,
"childFraction": 0.001
}
SLURM ワークロード マネージャーを使用してクラスター上で PIRA を実行するには、 --slurm-config
フラグを使用して PIRA を呼び出します。バッチ システム構成ファイルへのパスを指定します。接尾辞_Slurm
が付いている統合テスト ( test/integration/*_Slurm/
) を参照してください。 PIRA は現在、SLURM ワークロード マネージャーを使用したバッチ システムをサポートしています。 PIRA は、slurm クラスターにあるmodule
システムの使用をサポートしています。
バッチ システム構成ファイルは JSON ファイルであり、次のような構造になっています。
{
"general": {
"backend": "slurm",
"interface": "pyslurm",
"timings": "subprocess"
},
"module-loads": [
{
"name": "gcc",
"version": "8.5"
},
{
"name": "llvm",
"version": "10.0.0",
"depends-on": [
{
"name": "gcc",
"version": "8.5"
}
]
}
],
"batch-settings": {
"time_str": "00:10:00",
"mem_per_cpu": 3800,
"number_of_tasks": 1,
"partition": null,
"reservation": null,
"account": "your_account_here",
"cpus_per_task": 96
}
}
壊す:
general
セクション: PIRA がバッチ システム上でコードを実行する方法を選択できます。このセクションのすべてのオプションはオプションであるため、デフォルトを使用しても問題ない場合はセクション全体を省略できます。backend
: 使用するワークロード マネージャー。選択肢: slurm
、slurm ワークロード マネージャーの場合。デフォルト: slurm
、したがってオプション。interface
: PIRA がバッチ システム マネージャーと対話する方法。 SLURM バックエンドの場合、これらは次のとおりです: pyslurm
: PySlurm を使用する場合 (これには PySlurm のインストールが必要です、このセクションを参照してください); sbatch-wait
: --wait
フラグ付きの標準sbatch
使用する場合; os
: 標準sbatch
およびsqueue
対話呼び出しの場合。デフォルト: pyslurm
、したがってオプション。timings
: ターゲット コードのタイミングをどのように行うべきか。選択肢: subprocess
、サブプロセス内の Python ラッパーとos.times
を使用したタイミング用 (ローカルで実行した場合に PIRA が行うのとまったく同じです)。 os
、 /usr/bin/time
を使用します。デフォルト: subprocess
、したがってオプション。force-sequential
: デフォルトはfalse
。 true
に設定すると、PIRA/バッチ システムがすべての実行を順番に実行します (ターゲット コードは一度に 1 回だけ実行します)。これは、PIRA がバッチ システムで繰り返しを実行するだけでなく、スケーリング実験のさまざまなジョブを順番に実行することを意味します。 false
に設定した場合、PIRA はバッチ システムに対し、各反復内でできるだけ多くの実行を並行して実行するよう指示しようとします。module-loads
セクション:現在 PIRA では使用されていません。作業は進行中です。現在、PIRA を開始する前に、すべてのモジュールを手動でロードする必要があります。どのモジュールをmodule
システムでロードするかを意味します。これには、適切な場所に配置する必要があります (コマンドmodule load
およびmodule purge
PIRA によって使用される場合があります)。 module
システムが用意されていない場合、またはモジュール システムを使用したくない場合は、このセクションを完全に省略するか、 "module-loads": null
を設定します。 PIRA がロードするモジュールを指定するには、上の例のようにモジュールのリストを指定します。name
が必要です。version
はオプションであり、指定しない場合は、 module
システムがデフォルトのモジュール バージョンとしてロードするものによって異なります。常にバージョンを明示的に指定することをお勧めします。depends-on
もオプションです。このモジュールが依存するモジュールのリストを与えます。これらのモジュールにはname
が必要で、オプションでversion
を指定できます。ここで定義された依存関係は、モジュールをロードする順序を決定するために PIRA によって使用されます。null
に設定した場合、このモジュールには依存関係がないと想定されます。depends-on
指定されていない場合、PIRA は構成ファイルで指定された順序とまったく同じ順序でモジュールをロードしようとします。batch-setting
セクション: バッチ システムの実際のハードウェアとジョブ オプション。セクション内の一部のオプションは必須であるため、このセクションを省略することはできません。time
: sbatch --time
オプション、必須。mem-per-cpu
: sbatch --mem-per-cpu
オプション、必須。ntasks
: sbatch --ntasks
オプション、必須。partition
、 reservation
、 account
(デフォルトはすべてnull
= not provided)、 cpus-per-task
(デフォルトは4
)、 exclusive
(デフォルトはtrue
、 pyslurm
ではサポートされません)、およびcpu-freq
(デフォルトはnull
)。sbatch
オプションがいくつかあることに注意してください。これは、繰り返しをジョブ配列にマップするために PIRA が内部的に使用するいくつかのオプション ( --array
オプションなど) が原因です。 クラスターに PySlurm のどのバージョンをどのようにインストールするかは、SLURM のバージョンと SLURM のインストールによって大きく異なります。 PIRA を使用した pyslurm のインストールおよびパッケージ化ソリューションは進行中です。 README を参照してください。次のいくつかを試してみるとよいでしょう。
include
とlib
ディレクトリを探します。python3 setup.py build --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
python3 setup.py install --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
。