mcpField
R
rocprofiler-systems-instrumenting-binaries

rocprofiler-systems-instrumenting-binaries

github.com/amd開発482100 回インストール2 日前に更新
リポジトリ

rocprofiler-systems-instrumenting-binaries について

`rocprof-sys-instrument` で関数を選び、実行時インストルメンテーションまたはバイナリ書き換えを行うスキルです。対象範囲の設定、選択結果の事前確認、関数が対象に含まれる理由や除外される理由の調査に役立ちます。

主な機能

  1. 01実行時またはバイナリ書き換えの設定
  2. 02パターンによる関数とモジュールの選択
  3. 03対象関数と除外関数の事前確認
  4. 04サイズしきい値とループ計測の調整
  5. 05インストルメンテーション制約の診断

活用シーン

  1. 01アプリケーション内の指定関数の計測
  2. 02バイナリ書き換え前の対象範囲確認
  3. 03ライブラリ除外やしきい値変更による負荷軽減
  4. 04関数が計測対象にならない理由の調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/amd/skills --skill rocprofiler-systems-instrumenting-binaries

インストール後、Claude Code で/rocprofiler-systems-instrumenting-binariesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

.federated.json
skill-card.md
evals/
evals.json
machine.yml

詳細

バイナリの計測

rocprof-sys-instrument は、プログラムのどの関数を計測するかを決定し、プログラムの実行中に計測するか、新しい計測済みバイナリを書き出します。現在の全フラグ一覧を確認するには、rocprof-sys-instrument --help を実行してください(特定のフラグを確認するには --help | grep -A3 -- --<flag> を使用します)。

回答方法

回答は短くしてください。ユーザーが詳しい説明を求めていない限り、目安として約 1200 文字以内にします。最初に直接的な答えとコマンドを示し、その後は質問に当てはまるこのスキルの注意点だけを加えてください(例:バイナリの書き換えでは共有ライブラリが対象外であること、-MR は -R を無視すること、-l にはより小さい -i を組み合わせること、--print-available でモジュールを一覧表示できること)。求められていない代替案や背景情報は追加しないでください。

前提条件

  • rocprof-sys-instrument と rocprof-sys-run が PATH にあること。ない場合は source <install-prefix>/share/rocprofiler-systems/setup-env.sh を実行します。
  • 可能であれば、ターゲットを -g を付けてビルドしてください。モジュールがソースファイルになり、ツールがファイル名と行番号を報告できます。デバッグ情報がない場合、バイナリ全体がバイナリ名のモジュール 1 つとして扱われます。

実行時の計測とバイナリの書き換え

実行時の計測バイナリの書き換え
選択方法デフォルト(-o なし)-o [<output>]
コマンドrocprof-sys-instrument [opts] -- ./app argsrocprof-sys-instrument [opts] -o app.inst -- ./app
計測対象実行ファイルと読み込まれる共有ライブラリターゲット自身のコードのみ。共有ライブラリは計測されません
コスト(上流の指針)メモリ使用量が多く、セットアップが遅く、実行時のオーバーヘッドも大きいセットアップが大幅に速く、オーバーヘッドも小さい
アプリを実行するかはい。args を指定して直ちに実行しますいいえ。後で rocprof-sys-run -- ./app.inst args を実行します
ターゲットの後の引数アプリに渡されます無視されます(結果を実行するときに指定してください)
  • アプリが読み込むライブラリのパフォーマンスが重要な場合は、実行時の計測を選択します。
  • オーバーヘッドを最小限に抑えたい場合、繰り返し実行する場合、MPI アプリケーションの場合は、バイナリの書き換えを選択します(上流の指針)。
  • --exe-only(実行時の計測のみ)を指定すると、すべての共有ライブラリが対象外になります。 --max-library-functions N を指定すると、関数が N 個を超える共有ライブラリが対象外になります (デフォルトは 20000、0 はチェックを無効にします)。
  • ファイル名を指定せずに -o を指定すると、カレントディレクトリに <name>.inst(ターゲットがカレントディレクトリにある場合)、またはライブラリ用に instrumented/<name> が書き込まれます。

関数とモジュール

  • 関数は 1 つのシンボルです。たとえば big_a や Domain::BuildMesh です。
  • モジュールは関数が定義されているコンテナーです。バイナリにデバッグ情報がある場合はソースファイル(/path/mod_a.cpp)、ない場合はバイナリまたはライブラリ(/path/app)です。実行時モードでは、共有ライブラリはそれぞれ独立したモジュールとして表示されます。
rocprof-sys-instrument --simulate -o app.inst --print-available modules   -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-available functions -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-available pair      -- ./app

pair は、関数ごとに [module] --> [function][#instructions] という行を 1 つ出力します。 モジュールオプション(-MI、-ME、-MR)は、一致するモジュール内のすべての関数に適用されます。関数オプション(-I、-E、-R)は、個々の関数に適用されます。

インクルード、除外、制限

オプション意味
-I / -MI(インクルード)サイズのヒューリスティックでスキップされる場合でも、これらを強制的に含めます。他の対象は絞り込みません。
-R / -MR(制限)サイズのヒューリスティックを無視し、一致するものだけを計測します。
-E / -ME(除外)これらは計測しません。常に適用され、インクルードと制限より優先されます。

一致ルール(すべて検証済み):

  • パターンは正規表現で、名前の任意の箇所に一致します(部分一致であり、アンカーはありません)。tiny は tiny_a と tiny_b に一致します。完全一致にするには ^tiny_a$ と記述します。
  • 1つのオプションの後に複数のパターンを指定すると、OR 条件になります。-I tiny_a medium_b は -I 'tiny_a|medium_b' と同じです。
  • モジュールパターンはモジュール名(ソースファイルまたはバイナリパス)に一致します。関数パターンは関数名に一致し、--label args が設定されている場合はシグネチャにも一致します(そのため、-I '\(long int\)$' は --label args と組み合わせた場合のみ機能します)。
  • どの階層でも、除外はインクルードより優先されます。-ME 'mod_' -I tiny_a では何も計測されません。
  • -MR mod_a は、サイズのしきい値にかかわらず、mod_a のすべての関数を計測します。サイズの小さい関数やループを含む関数も対象です。

注意点:--module-restrict と --function-restrict の両方を指定すると、関数の制限は警告なしに無視されます。-MR mod_a -R '^medium_b$' では、上流のドキュメントに記載された和集合ではなく、mod_a のすべての関数が計測されました。どちらか一方を使うか、-MR と -E を組み合わせてください。

例:

# Only one source file
rocprof-sys-instrument -o app.inst -MR 'solver\.cpp$' -- ./app
# Everything the heuristics pick, minus one noisy library
rocprof-sys-instrument -o app.inst -ME 'libm\.so' -- ./app
# Add a small function the heuristics skip
rocprof-sys-instrument -o app.inst -I '^small_helper$' -- ./app

ドライラン

ドライランでは、実際に計測せずに、計測対象となるものを確認できます。

rocprof-sys-instrument --simulate [options] -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-instrumented pair -- ./app
rocprof-sys-instrument --dump-info --simulate -o app.inst -- ./app

--simulate の動作(検証済み):

  • 解析後に終了します。アプリケーションは実行されず、-o を指定していても書き換え後のバイナリは出力されません。
  • モジュールごとの概要(<module> で計測された関数の数)を出力します。
  • --print-available、--print-instrumented、--print-excluded、--print-coverage、または --print-overlapping を指定すると、それらのリストも出力されます。それぞれ functions、modules、または pair を指定します。+ 形式(functions+、pair+)では、--label args が使用されている場合に関数シグネチャも表示されます。

--dump-info の動作:

  • available、instrumented、excluded、overlapping のレポートを .txt および .json 形式で rocprofsys-<name>-output/instrumentation/ に書き込みます。<name> は対象(実行時)または -o で指定した出力名(書き換え時。例:rocprofsys-app.inst-output)です。
  • --print-format json(または txt)を指定すると、形式を限定できます。ディレクトリを変更するには ROCPROFSYS_OUTPUT_PATH を設定します。テストしたどちらのビルドでも、--print-dir は効果がありませんでした。
  • .txt ファイルには、アドレス、アドレス範囲、命令数、リンケージ、可視性、モジュール、関数が記載されます。.jsonファイルには、関数ごとのheuristics` ブロックも含まれます(「Why is a function missing?」を参照)。

--simulate を指定しない場合、--dump-info は通常どおり書き換え後のバイナリも生成します。

ワークフロー:ドライランを実行し、instrumented と excluded を確認して、正規表現またはしきい値を調整します。これを繰り返した後、--simulate を外します。

粒度

関数が計測されるのは、サイズに関する両方のチェック(検証済み)を通過した場合のみです。

  • --min-instructions 以上の命令数(デフォルトは 1024)
  • --min-address-range バイト以上のアドレス範囲(デフォルトは命令数の最小値の 4 倍、つまり 4096)

意外に思われる動作:

  • -i N だけを指定すると、アドレス範囲の最小値が 0 に設定されます(命令数のみが条件になります)。-r N だけを指定すると、命令数の最小値が 0 に設定されます。両方を指定すると、両方が適用されます。したがって、-i 0 または -r 0 を指定すると、両方のサイズチェックが無効になります。ただし、すべての関数が計測されるわけではありません。関数は、少なくとも 2 つの命令を含み、Dyninst で計測可能であり、除外、重複、トラップ、リンケージ、可視性の各チェックを通過する必要があります。また、プロファイラー自身のモジュールやシステムモジュールから関数が取得されることはありません。
  • 環境変数 ROCPROFSYS_DEFAULT_MIN_INSTRUCTIONS は、命令数の最小値のデフォルトを変更し、それに伴って範囲のデフォルト値も変更します。
  • ループを含む関数には --min-instructions-loop と --min-address-range-loop が適用されます。これらは、設定されていない場合、ループを含まない関数の値に従います。これらのオプションによって、ループを含む関数を計測するかどうかが決まります。
  • -l/--instrument-loops を指定すると、計測対象の関数内のループも追加で計測されます。プロファイルでは、各ループはソース範囲を名前に含む子エントリーとして表示されます。たとえば、loop_a [{449,54}-{449,83}] のように表示され、関数自体のセルフタイムはそれに応じて減少します。

小規模なテストプログラムの例(命令数:7、16、79、429、3657):

オプション計測される関数
デフォルト命令数 3657 の関数のみ
-i 100命令数 429 と 3657 の関数
-i 20命令数 79、429、3657 の関数
-i 05 つすべて
-i 50 -r 1000命令数 429 と 3657 の関数(命令数 79 の関数は 278 バイトのみです)

詳細を増やすと、オーバーヘッドとトレースのサイズも増加します。ホットコードの内部を確認するにはしきい値を下げるか、-l を追加してください。オーバーヘッドを抑えるには、しきい値を上げる、対象モジュールを絞る、または --exe-only を使用してください。その他の条件(--dynamic-callsites、--traps、--loop-traps、--allow-overlapping、--linkage、--visibility)については、--help を参照してください。

関数が見つからない、またはデータが多すぎる場合

関数が見つからない場合:

  1. 除外された内容を一覧表示します:--simulate --print-excluded pair、または --dump-info --simulate を実行します。
  2. excluded.json を開き、対象の関数を見つけて heuristics ブロックを確認します (should_instrument: false が判定結果です)。フィールドには2種類あり、原因を示す値はそれぞれ異なります。
    • 機能フィールド:false が原因です。 is_instrumentable、 can_instrument_entry、can_instrument_exit が false の場合、Dyninst には関数のエントリポイントまたは出口ポイントとして使用できるものがありません。この問題を解決するオプションはないため、そのまま受け入れるか、呼び出し元を計測してください。
    • 制約フィールド:true が原因です。
      • is_address_range_constrained、is_num_instructions_constrained(および is_loop_* 系):小さすぎます。-i/-r の値を下げるか、-I を追加します。
      • is_user_excluded:指定した -E/-ME パターンのいずれかに一致しています。
      • is_user_restricted:-R/-MR パターンに一致していません。
      • is_overlapping_constrained:--allow-overlapping が必要です。
      • is_entry_trap_constrained、is_exit_trap_constrained:--traps が必要です。
      • is_linkage_constrained、is_visibility_constrained:--linkage、--visibility を参照してください。
      • is_internal_constrained:プロファイラー自身のライブラリに属しています。
      • is_module_constrained:そのモジュールは、プロファイラーが計測しないものです (システムライブラリ、Dyninst、またはプロファイラー自身のライブラリ)。
      • is_routine_constrained:その名前は、プロファイラーが計測しないものです。
    • フィールドがない場合: 命令数が2未満の関数は常にスキップされます。 すべての機能フィールドが true で、制約フィールドが1つも true でない場合は、 num_instructions を確認してください(検証済み:-i 0 を指定しても、命令が1つの関数は除外されたままです)。
  3. 関数が共有ライブラリにある場合、バイナリ書き換えでは対象にならないことに注意してください。

データが多すぎる場合、または処理が遅すぎる場合:-i の値を上げ、対象のモジュールに絞り込み(-MR)、ノイズとなるモジュールを除外し(-ME)、-l を省略するか、--exe-only を追加します。

ライブラリ、RPATH、トラブルシューティング

通常の実行ファイルが計測済みのコピーを読み込むように共有ライブラリを書き換えるには:

rocprof-sys-instrument -o ./app.inst -- ./app
mkdir inst && rocprof-sys-instrument -o inst/libfoo.so -- ./libfoo.so
LD_LIBRARY_PATH=$PWD/inst:$LD_LIBRARY_PATH rocprof-sys-run -- ./app.inst
ldd ./app.inst | grep libfoo      # must resolve into inst/
  • 書き換え後のライブラリのファイル名(libfoo.so、または ldd に表示される soname)はそのままにし、別のディレクトリに書き込みます。
  • RPATH と RUNPATH: ローダーは LD_LIBRARY_PATH より先に DT_RPATH ディレクトリを検索するため、元のライブラリが RPATH ディレクトリにある場合は、書き換えたコピーではなく元のライブラリが読み込まれます。 RPATH ディレクトリにライブラリがない場合は LD_LIBRARY_PATH が引き続き使われ、RUNPATH を持つバイナリでは LD_LIBRARY_PATH が先に検索されます。 objdump -p <exe> | egrep 'RPATH|RUNPATH' と ldd で確認してください。ldd に元のライブラリが表示される場合に限り、バイナリを修正してください。-Wl,--enable-new-dtags を指定して再リンクするか、patchelf でエントリを変更します: patchelf --remove-rpath <exe> を実行すると LD_LIBRARY_PATH が優先され、patchelf --set-rpath <dir> <exe> を実行すると RUNPATH が書き込まれるため、こちらも同様です。--force-rpath を追加すると DT_RPATH が維持され、問題が再発します。
  • 実行時ターゲットとしてのライブラリ: rocprof-sys-instrument -- ./libfoo.so を実行すると 「実行可能ファイルではありません……バイナリ書き換えモードに切り替え、'--simulate --all-functions' を仮定します」と表示されるため、ドライランの近似結果が得られるだけで、実行は行われません。 -f/--force は、名前がライブラリのように見える実行ファイル専用です。実際の .so に対して強制すると、テストでは Dyninst 内部で異常終了しました。
  • Main 関数が見つからない場合: -m <symbol>(または --main-function)を指定します。
  • 「Failed to transform trace ... in function ''」(上流プロジェクトのガイダンスであり、再現はしていません):-E '<f>' を追加します。その関数とコードを共有する関数によって、引き続き取り込まれる可能性があります。それらも除外するか、-ME でモジュール全体を除外してください。

結果の実行とデフォルト値の埋め込み

  • 書き換えたバイナリを rocprof-sys-run -- ./app.inst args で実行すると、計測対象の関数がほかの関数と同様にプロファイルまたはトレースに表示されます。
  • --env VAR=VALUE ... を指定すると、新しいバイナリにデフォルト値が埋め込まれるため、後続のセッションで環境変数をエクスポートする必要がありません。実行時に設定された変数は、埋め込み値より優先されます(ROCPROFSYS_PROFILE で確認済みです)。
  • --label args file line return を指定すると、その情報が関数名に追加されます(args を指定した場合、big_a(long int) のようになります)。
  • -M sampling を指定すると、サンプラーの開始と停止のために main のみが計測されます(確認済み)。このオプションは上流では非推奨です。サンプリングには rocprof-sys-sample またはプリセットを使用してください。

よくある間違い

間違い修正方法
バイナリの書き換えで共有ライブラリも計測されると思い込む対象バイナリ自身のコードのみが対象です。ランタイムモードを使うか、ライブラリも書き換えてください。
選択範囲を絞るために -I を使う-I は追加のみです。-R/-MR で絞り込むか、-E/-ME で除外してください。
-I tiny と書いて完全一致を期待するパターンはアンカーなしの部分文字列として扱われます。^tiny_a$ を使ってください。
-MR と -R を組み合わせる関数の制限は無視されます。どちらか一方を使うか、-MR と -E を組み合わせてください。
-i だけを小さくしても範囲指定が適用されると思い込む一方のオプションを指定すると、もう一方は 0 に設定されます。両方を適用するには、両方を指定してください。
書き換え時にターゲットの後ろにアプリケーションの引数を渡す引数は無視されます。rocprof-sys-run -- ./app.inst args に渡してください。
DT_RPATH を持つバイナリの隣に書き換えたライブラリを置くLD_LIBRARY_PATH は無視されます。objdump -p で確認し、再リンクするか rpath を修正してください。
--simulate -o でバイナリが生成されると思い込むドライランではレポートのみが書き込まれます。--simulate を削除してください。
--print-dir に頼るテスト済みのビルドでは効果がありませんでした。ROCPROFSYS_OUTPUT_PATH を使ってください。

コメント