rocprofiler-systems-instrumenting-binaries について
`rocprof-sys-instrument` で関数を選び、実行時インストルメンテーションまたはバイナリ書き換えを行うスキルです。対象範囲の設定、選択結果の事前確認、関数が対象に含まれる理由や除外される理由の調査に役立ちます。
主な機能
- 01実行時またはバイナリ書き換えの設定
- 02パターンによる関数とモジュールの選択
- 03対象関数と除外関数の事前確認
- 04サイズしきい値とループ計測の調整
- 05インストルメンテーション制約の診断
活用シーン
- 01アプリケーション内の指定関数の計測
- 02バイナリ書き換え前の対象範囲確認
- 03ライブラリ除外やしきい値変更による負荷軽減
- 04関数が計測対象にならない理由の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ amd/ skills --skill rocprofiler-systems-instrumenting-binariesインストール後、Claude Code で/rocprofiler-systems-instrumenting-binariesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.federated.jsonskill-card.mdevals/evals.jsonmachine.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 args | rocprof-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 0 | 5 つすべて |
-i 50 -r 1000 | 命令数 429 と 3657 の関数(命令数 79 の関数は 278 バイトのみです) |
詳細を増やすと、オーバーヘッドとトレースのサイズも増加します。ホットコードの内部を確認するにはしきい値を下げるか、-l を追加してください。オーバーヘッドを抑えるには、しきい値を上げる、対象モジュールを絞る、または --exe-only を使用してください。その他の条件(--dynamic-callsites、--traps、--loop-traps、--allow-overlapping、--linkage、--visibility)については、--help を参照してください。
関数が見つからない、またはデータが多すぎる場合
関数が見つからない場合:
- 除外された内容を一覧表示します:
--simulate --print-excluded pair、または--dump-info --simulateを実行します。 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つの関数は除外されたままです)。
- 機能フィールド:false が原因です。
- 関数が共有ライブラリにある場合、バイナリ書き換えでは対象にならないことに注意してください。
データが多すぎる場合、または処理が遅すぎる場合:-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 を使ってください。 |