PDF:

Linux on POWER のパフォーマンスを評価する
Linux ツールを使用してパフォーマンスを分析する
Adhemerval Zanella Netto
Software Engineer
IBM
2012年 7月 12日
Ryan S. Arnold
Advisory Software Engineer
IBM China
コンパイル言語 (C または C++) 環境に焦点を当てた Linux on POWER のパフォーマンス問題
を評価する方法を学んでください。この記事では、POWER7 の CPI モデルを解説し、一般
に入手できる Linux ツールを使って潜在的な CPU ストール、パイプライン・ハザード、そ
してパフォーマンス問題を明らかにする方法を具体的に紹介します。最後のセクションで
は、POWER7 のアルゴリズムを分析し、最適化を行います。
はじめに
最近のマシンにおける、アプリケーションのパフォーマンス評価は複雑なタスクになりがちで
す。そのため、手近に使えるツールでは、パフォーマンスに関するすべての変数に対処しきれま
せん。また、それぞれのワークロードがどのコンピューター・サブシステムにストレスをかける
かは、ワークロードによって異なり、CPU バウンドなプログラムを測定して調整することと、I/
O バウンドなプログラムやメモリー・バウンドなプログラムを調整することには大きな違いがあ
ります。この記事ではコンパイル済み言語環境 (C、C++、その他) でのCPU バウンドなプログラム
とメモリー・バウンドなプログラムに焦点を当て、以下のタスクを行う方法を具体的に説明しま
す。
• プログラムのホットスポット (プログラムの中で命令が実行される割合が高い領域、関数、
メソッド) を見つける
• プロセッサーに用意されているハードウェア・パフォーマンス・カウンターを使用して
POWER7 上でのプログラムの動作状況を測定する
• Linux でパフォーマンス評価に使用できるツールを識別する
POWER7 の CPI モデル
アプリケーションのパフォーマンス分析について理解するには、まず、CPI メトリックの説明か
ら始めます。CPI (Cycles per Instruction) メトリックとは、1 つの命令を完了するために必要なプ
© Copyright IBM Corporation 2012
Linux on POWER のパフォーマンスを評価する
商標
ページ 1 / 24
developerWorks®
ibm.com/developerWorks/jp/
ロセッサー・サイクル数です。命令はそれぞれ複数のステージに分割されて処理されます。典
型的な RISC パイプラインでは、「命令フェッチ」ステージの後、「命令デコード/レジスター・
フェッチ」、「実行」、オプションの「メモリー・アクセス」と続き、最後に「ライトバック」
が行われます。CPU の CPI メトリックを改善するには (つまり、測定される CPI 値を小さくするに
は)、命令レベルの並列処理を利用するという方法があります。これは、複数のステージで、それ
ぞれのステージが異なる命令を処理するということです。最適化の際には、CPI 値を最小限にして
システムを最大限使用するように心掛けてください。パイプライン化されたプロセッサーで最適
化された命令フローの一例を図 1 に示します。
図 1. パイプライン化されたプロセッサーで最適化された命令フローの一例
あるステージが他のステージから完全には独立していないこともあります。つまり、依存関係の
ある命令が発行されると、プロセッサーはその依存関係を満たしてからでないと、命令の実行を
続けられません。例えば、メモリー・ロードの後に演算命令が続く場合、プロセッサーはキャッ
シュまたはメモリーへのデータの取り込みが完了してからでないと、演算命令を発行することが
できません。このような事態が起こり、パイプラインが停止することを、プロセッサーのパイプ
ラインで「ストール」が発生したと言います。図 2 に、パイプラインでストールが発生する様子
を示します。
図 2. パイプライン化されたプロセッサーでストールが発生する様子
図 1 と図 2 の例を比較してみると、図 1 のようにパイプラインが完全に満たされている場合 (サイ
クルごとに 1 つの命令が完了するパイプラインの場合)、クロックが 11 サイクル動作する間にプ
ロセッサーは 8 つの命令を実行することができますが、図 2 のように 3 つのサイクルでストール
が発生する場合、同じ 11 サイクルでも 5 つの命令しか実行されません。このパフォーマンス損失
は、約 40% です。アルゴリズムによっては、ある程度のストールが不可避であることもあります
が、慎重に分析することで、ストールが発生しないようにコードの一部を書き直すか、調整する
方法を知る手掛かりやヒントを得ることができます。最近の CPU パイプライン化、および命令レ
ベルの並列性についての詳細は、記事「Modern Microprocessors - A 90 Minute Guide」で教訓的に
説明しています (「参考文献」を参照)。
CBM (CPI Breakdown Model) は、機能別のプロセッサー・ステージにパフォーマンス・カウン
ターを関連付けて、CPU のどの機能ユニットがストールを発生させているかを明らかにするた
めのモデルです。CBM は CPU のアーキテクチャーとプロセッサー・モデルに依存するため、例
Linux on POWER のパフォーマンスを評価する
ページ 2 / 24
ibm.com/developerWorks/jp/
developerWorks®
えば Power Architecture と Intel Architecture の CBM はまったく異なります。また、POWER5 と
POWER7 でも、その CBM は似ているとは言え、同じではありません。図 3 に、POWER7 CBM の一
部を抜粋したものを示します (図 3 の情報をテキストとして表示したものを見るにはここをクリッ
クしてください)。
図 3. POWER7 CBM の一部抜粋
Power Architecture でのハードウェア・パフォーマンス・カウンターは、プロセッサー内で特定の
イベントが発生すると更新される、一連の特殊用途のレジスターです。POWER7 プロセッサーに
は、PMU (Performance Monitoring Unit) が内蔵されており、PMU ごとに 6 つのスレッド・レベル
の PCM (Performance Counter Monitor) があります。そのうち 4 つはプログラマブル PCM です。
これはつまり、発生する可能性のある 500 以上のパフォーマンス・イベントのうち、同時に 4 つ
のイベントを監視できることを意味します。POWER7 のパフォーマンス・カウンターはグループ
Linux on POWER のパフォーマンスを評価する
ページ 3 / 24
developerWorks®
ibm.com/developerWorks/jp/
別に定義されていて、PMU が同時に監視できるのは、同じグループのイベントに限られます。図
3 に示されているのは、POWER7 CBM の定義に使用されているパフォーマンス・カウンターのサ
ブセットです。図 3 のカウンターがプロファイルで使用されて、プロセッサー・ストールの原因
となっている CPU の機能ユニットを示すとともに、ストールを廃絶するためにアルゴリズムを調
整する方法を知る手掛かりを提供します。
図 3 で背景が白のボックスは、プロファイルで監視される POWER7 の具体的な PCM です。これら
の値に基づき、グレーのボックス (アスタリスク (*) が付けられています) が計算されます (これら
のメトリックには、固有のハードウェア・カウンターがありません)。
注: POWER7 の包括的な PMU リファレンスとなる「Comprehensive PMU Event Reference
POWER7」を参照してください (「参考文献」を参照)。
Linux でのツール
POWER7 プロセッサーの PCM は、どのように利用できるのでしょうか? POWER では、ハード
ウェア割り込み、コード・インスツルメンテーション (gprof など)、動作関連のシステム・フック
(systemtap) など、各種のプロファイリング手法を使用できますが、PCM にはプロセッサー機能と
直接連動する広範なカウンターが揃っています。PCM プロファイラーはオペレーティング・シス
テム割り込みを使用して、常時一定の間隔でプロセッサー・レジスターの値をサンプリングしま
す。命令トレースの結果と比べると、サンプル・プロファイリングによる結果は数値的な精度に
劣るかもしれませんが、全体的なシステム・パフォーマンスへの影響は小さいため、ターゲット
とするベンチマークをほぼフルスピードで実行することができます。生成されるデータは正確で
ないにしても、許容誤差の範囲内の近似値です。
Linux での PCM プロファイリングに最もよく使われているツールには、OProfile と perf の 2 つが
あります (「参考文献」を参照)。両方とも動作原理は同じで、ワークロードのバックトレースと
併せて、常に (syscall によって) 特殊なハードウェア・レジスターをサンプリングしますが、その
構成と使用方法はそれぞれに異なります。
Linux システムの OProfile ツールは、すべての実行中コードを低オーバーヘッドでプロファイ
リングできる、システム規模のプロファイラーです。このツールは、カーネル・ドライバー、
サンプル・データを収集するデーモン、そしてプロファイリング後にデータを情報に変換す
るための数個のツールからなります。アノテーション付きのソースを必要とするのでない限
り、デバッグ・シンボル (gcc の -g オプション) は必要ありません。最近の Linux 2.6 カーネルで
は、OProfile が gprof スタイルのコール・グラフ・プロファイル情報を提供できるようになって
います。OProfile の通常のオーバーヘッドは 1% から 8% です (サンプリング間隔とワークロード
に依存)。
POWER 上では、OProfile はパフォーマンス・ハードウェア・カウンターのグループとパフォーマ
ンス・カウンターのグループを監視することによって機能します。ただし、異なるグループを同
時に使用することはできません。これは、同じワークロードから異なる複数のパフォーマンス・
カウンターを取得するためには、異なる OProfile イベント構成でワークロードを複数回実行し
なければならないことを意味します。つまり、POWER7 CBM 全体を一度に監視できないというこ
とでもあります。使用可能なグループについては、前述の「Comprehensive PMU Event Reference
Linux on POWER のパフォーマンスを評価する
ページ 4 / 24
ibm.com/developerWorks/jp/
developerWorks®
POWER7」に記載されている「Detailed Event Descriptions」を参照するか、リスト 1 のコマンドを
実行して調べてください。
リスト 1. OProfile グループの一覧表示
# opcontrol -l
リスト 2 に、単純な OProfile の構成および起動コマンドを記載します。
リスト 2. OProfile POWER7 CPU サイクルの構成
# opcontrol -l
# opcontrol -–no-vmlinux
# opcontrol -e PM_CYC_GRP1:500000 -e PM_INST_CMPL_GRP1:500000 -e PM_RUN_CYC_GRP1:500000
-e PM_RUN_INST_CMPL_GRP1:500000
# opcontrol --start
ワークロードを実行するコマンドはリスト 3 のとおりです。
リスト 3. OProfile 実行コマンド・シーケンス
# opcontrol --dump
# opcontrol –-stop
# opcontrol --shutdown
パフォーマンス・カウンター・レポートを取得するには、リスト 4 のコマンドを実行します。
リスト 4. OProfile レポートの生成
# opreport -l > workload_report
注: developerWorks の記事「Identify performance bottlenecks with OProfile for Linux on POWER」
(「参考文献」を参照) は、OProfile の包括的なガイドになります (ただし、POWER7 用に更新され
てはいません)。
Linux カーネル 2.6.29 で導入された perf ツールは、ハードウェア・レベルとソフトウェア・レベ
ルの両方でパフォーマンス・イベントを分析します。perf ツールの利点は、OProfile のようにシ
ステム指向ではなく、プログラム指向であることです。このツールには、事前設定された「cpucycles OR cycles」、「branch-misses」、「L1-icache-prefetch-misses」などのパフォーマンス・カ
ウンターがあります。また、サンプルの精度は犠牲になりますが、PMU グループを多重化して、
異なるグループから同時に複数のパフォーマンス・カウンターを収集することもできます。
perf ツールの欠点は、ハードウェア・パフォーマンス・カウンターを直接収集できるとは言
え、POWER7 CBM が示すカウンター名を認識しないことです。したがって、16 進数をそのまま使
用しなければなりません。表 1 に、OProfile イベントと 16 進数のマッピングを記載します。こ
のマッピングを使用すれば、(16 進数のままでイベントを記録するオプションを使用した) perf で
POWER7 の CBM を利用することができます。
表 1. POWER7 の perf で認識可能な 16 進のイベント・コード
カウンター
Linux on POWER のパフォーマンスを評価する
16 進のイベント・コード
ページ 5 / 24
developerWorks®
ibm.com/developerWorks/jp/
PM_RUN_CYC
200f4
PM_CMPLU_STALL
4000a
PM_CMPLU_STALL_FXU
20014
PM_CMPLU_STALL_DIV
40014
PM_CMPLU_STALL_SCALAR
40012
PM_CMPLU_STALL_SCALAR_LONG
20018
PM_CMPLU_STALL_VECTOR
2001c
PM_CMPLU_STALL_VECTOR_LONG
4004a
PM_CMPLU_STALL_LSU
20012
PM_CMPLU_STALL_REJECT
40016
PM_CMPLU_STALL_ERAT_MISS
40018
PM_CMPLU_STALL_DCACHE_MISS
20016
PM_CMPLU_STALL_STORE
2004a
PM_CMPLU_STALL_THRD
1001c
PM_CMPLU_STALL_IFU
4004c
PM_CMPLU_STALL_BRU
4004e
PM_GCT_NOSLOT_CYC
100f8
PM_GCT_NOSLOT_IC_MISS
2001a
PM_GCT_NOSLOT_BR_MPRED
4001a
PM_GCT_NOSLOT_BR_MPRED_IC_MISS
4001c
PM_GRP_CMPL
30004
PM_1PLUS_PPC_CMPL
100f2
注: IBM の Wiki「Using perf on POWER7 systems」(「参考文献」を参照) は、perf の包括的なガイ
ドになります (ただし、POWER7 用に更新されてはいません)。
OProfile に定義されている POWER7 イベントに対応した、perf で使用可能な 16 進のイベント・
コードを libpfm4 プロジェクト (「参考文献」を参照) から取得することができます。これらの
コードは、POWER7 専用のヘッダー (lib/events/power7_events.h) 内で定義されています。サンプ
ル・プログラム examples/showevtinfo にも、イベント名とそれぞれに対応する 16 進コードが示さ
れています。
カウンター情報を取得する手法としては、プロファイリングが一般的です。プロファイリングに
より、開発者はコードの実行およびデータ・アクセスにおけるホットスポットを特定したり、
パフォーマンスの影響を受けやすい領域を突き止めたり、メモリー・アクセス・パターンを理
解したりするなど、さまざまな実態を明らかにすることができます。プロファイリングを開始す
るには、まずその前に、パフォーマンス評価の戦略を練り上げる必要があります。プログラムに
は、各種のモジュールや DSO (Dynamic Shared Object: 動的共有オブジェクト) で構成されている
もの、カーネルを集中的に使用するもの、データ・パターン・アクセスへの依存度が高いもの (つ
まり、L2 または L3 キャッシュ・アクセスへの負担が高いもの)、あるいはベクトル演算ユニット
に重点を置くものなど、さまざまな特性があります。次のセクションでは、考えられるパフォー
マンス評価の戦略に目を向けます。
Linux on POWER のパフォーマンスを評価する
ページ 6 / 24
ibm.com/developerWorks/jp/
developerWorks®
パフォーマンス評価の戦略
パフォーマンス評価の初期段階では、CPU サイクル使用状況カウンターを調べて、プログラムの
ホットスポットを見つけます。この評価を POWER7 で行う場合には、表 2 に記載するイベントを
監視します。
表 2. POWER7 の CPU サイクル使用状況カウンター
カウンター
内容
PM_CYC
プロセッサー・サイクル
PM_INST_CMPL
完了した PowerPC 命令の数
PM_RUN_CYC
実行ラッチによってゲート制御されるプロセッサー・サイクル。オペ
レーティング・システムは、有用な処理を行っているときに実行ラッ
チを使用してそのことを示します。実行ラッチは通常、OS アイドル・
ループでクリアされます。実行ラッチによってゲート制御すると、ア
イドル・ループが除外されます。
PM_RUN_INST_CMPL
完了した実行命令の数
以上のイベントで OProfile を実行すると、シンボルにプロセッサーが費やした合計時間が示さ
れます。以下に、IBM Advance Toolchain 5.0 for POWER でコンパイルされた SPECcpu2006 ベンチ
マーク・スイートに含まれる 403.gcc コンポーネントに対するプロファイリングの出力例を記載し
ます。コマンド opreport -l による出力は以下のとおりです。
リスト 5. 403.gcc ベンチマークに対する「opreport -l」の出力 (カウンター
PM_CYC_GRP1 および PM_INST_CMPL_GRP1)
CPU: ppc64 POWER7, speed 3550 MHz (estimated)
Counted PM_CYC_GRP1 events ((Group 1 pm_utilization) Processor Cycles) with a unit
mask of 0x00 (No unit mask) count 500000
Counted PM_INST_CMPL_GRP1 events ((Group 1 pm_utilization) Number of PowerPC
Instructions that completed.) with a unit mask of 0x00 (No unit mask) count 500000
samples
204528
%
samples
32132
%
7.9112
1.3848
image name
gcc_base.none
app name
gcc_base.none
125218
113190
90316
89978
4.8434
4.3782
3.4934
3.4804
246710
50950
22193
11753
10.6324
2.1958
0.9564
0.5065
gcc_base.none
libc-2.13.so
gcc_base.none
vmlinux
gcc_base.none
libc-2.13.so
gcc_base.none
vmlinux
88429
3.4204
130166
5.6097
gcc_base.none
gcc_base.none
67720
56613
53949
2.6194
2.1898
2.0868
41479
89418
6985
1.7876
3.8536
0.3010
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
51587
1.9954
26000
1.1205
gcc_base.none
gcc_base.none
48050
47115
1.8586
1.8224
16086
33772
0.6933
1.4555
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
symbol name
reg_is_remote_cons\
tant_p.isra.3.part.4
bitmap_operation
memset
compute_transp
.pseries_dedicated_\
idle_sleep
bitmap_element_\
allocate
ggc_set_mark
canon_rtx
delete_null_\
pointer_checks
ggc_mark_rtx_\
children_1
single_set_2
note_stores
リスト 6. 403.gcc ベンチマークに対する「opreport -l」の出力 (カウンター
PM_RUN_CYC_GRP1 および PM_RUN_INST_CMPL_GRP1)
Counted PM_RUN_CYC_GRP1 events ((Group 1 pm_utilization) Processor Cycles gated by the
run latch. Operating systems use the run latch to indicate when they are doing useful
work. The run
latch is typically cleared in the OS idle loop. Gating by the run latch filters out
Linux on POWER のパフォーマンスを評価する
ページ 7 / 24
developerWorks®
ibm.com/developerWorks/jp/
the idle loop.) with a unit mask of 0x00 (No unit mask) count 500000
Counted PM_RUN_INST_CMPL_GRP1 events ((Group 1 pm_utilization) Number of run
instructions completed.) with a unit mask of 0x00 (No unit mask) count 500000
samples
204538
%
samples
32078
%
8.3658
1.3965
samples %
gcc_base.none
app name
gcc_base.none
124596
112326
90312
0
5.0961
4.5943
3.6939
0
252227
50890
21882
0
10.9809
2.2155
0.9527
0
gcc_base.none
libc-2.13.so
gcc_base.none
vmlinux
gcc_base.none
libc-2.13.so
gcc_base.none
vmlinux
88894
3.6359
124831
5.4346
gcc_base.none
gcc_base.none
67995
56460
54076
2.7811
2.3093
2.2118
41331
89484
6965
1.7994
3.8958
0.3032
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
51228
2.0953
26057
1.1344
gcc_base.none
gcc_base.none
48057
47160
1.9656
1.9289
16005
33766
0.6968
1.4700
gcc_base.none
gcc_base.none
gcc_base.none
gcc_base.none
symbol name
reg_is_remote_consta\
nt_p.isra.3.part.4
bitmap_operation
memset
compute_transp
.pseries_dedicated\
_idle_sleep
bitmap_element_all\
ocate
ggc_set_mark
canon_rtx
delete_null_pointer\
_checks
ggc_mark_rtx_childr\
en_1
single_set_2
note_stores
出力には、監視されたイベントのそれぞれが一対の列によって表されます。最初の列には、指定
のイベントの PCM から収集されたサンプル数が示されており、2 番目の列には、そのサンプル数
が合計サンプル数に占める割合がパーセントで示されています。このレポートに示されているよ
うに、プロセッサー・サイクルの大部分を消費しているのはシンボル reg_is_remote_constant_p
です。したがって、これがコード最適化の有力候補となります。このプロファイルは、どのシン
ボルが最も CPU サイクルを消費しているかを明らかにするだけで、プロセッサー・パイプライン
が完全に使用されているかどうかは識別しません。パイプラインの使用状況を調査するには、カ
ウンターの結果を比較します。
リスト 5 でカウンター PM_INST_CMPL_GRP1 (2 番目の列の対) を見ると、シンボル
bitmap_operation はシンボル reg_is_remote_constant_p よりも高いパーセンテージを示してい
ます。PM_CYC_GRP1 は使用された CPU サイクル数を意味するだけですが、このパフォーマン
ス・カウンターは、プロセッサー命令が完了するごとにインクリメントされます。詳しく分析す
る前の段階では、これはシンボル reg_is_remote_constant_p に、シンボル bitmap_operation よ
りも多くの CPU ストールが含まれていることを意味する可能性があります。これは、シンボル
reg_is_remote_constant_p の完了済み命令の数のほうが大幅に少ないためです。このプロファイ
ルが、今後の最適化作業で重点に置くシンボルを突き止めるための最初のヒントとなります。
コードの内容を詳しく分析する前に、ワークロードが CPU バウンドかメモリー・バウンドかを理
解しておくのが賢明です。このことが重要になるのは、それぞれのワークロードのタイプによっ
て、最適化手法がかなり異なるためです。例えば、メモリー・アクセスのほとんどを (NUMA リ
モート・ノード・メモリー・アクセスではなく) キャッシュまたはメイン・メモリーが占めている
場合、パフォーマンスはほぼ完全に、使用されているアルゴリズムとデータ構造に依存します。
メモリー・アクセス・パターンを調査するには、以下の表 3 に記載する 2 つのパフォーマンス・
カウンターを監視します。
表 3. POWER7 のメモリー使用状況カウンター
カウンター
PM_MEM0_RQ_DISP
Linux on POWER のパフォーマンスを評価する
内容
メイン・メモリーに対する読み取り要求の数
ページ 8 / 24
ibm.com/developerWorks/jp/
PM_MEM0_WQ_DISP
developerWorks®
メイン・メモリーに対する書き込み要求の数
この 2 つのカウンターから、メモリー・アクセス・パターンが主にメモリーの読み取りによる
ものか、書き込みによるものか、あるいはその両方によるものかがわかります。前と同じベンチ
マーク (SPECcpu2006 による 403.gcc) を使用すると、プロファイルには以下の内容が示されます。
リスト 7. 403.gcc ベンチマークに対する「opreport -l」の出力 (カウンター
PM_MEM0_RQ_DISP および PM_MEM0_WQ_DISP)
CPU: ppc64 POWER7, speed 3550 MHz (estimated)
Counted PM_MEM0_RQ_DISP_GRP59 events ((Group 59 pm_nest2) Nest events (MC0/MC1/PB/GX),
Pair0 Bit1) with a unit mask of 0x00 (No unit mask) count 1000
Counted PM_MEM0_WQ_DISP_GRP59 events ((Group 59 pm_nest2) Nest events (MC0/MC1/PB/GX),
Pair3 Bit1) with a unit mask of 0x00 (No unit mask) count 1000
samples %
samples %
app name
symbol name
225841
25.8000 289
0.4086 gcc_base.none
reg_is_remote_constant_p.\
isra.3.part.4
90068
10.2893 2183
3.0862 gcc_base.none
compute_transp
54038
6.1733 308
0.4354 gcc_base.none
single_set_2
32660
3.7311 2006
2.8359 gcc_base.none
delete_null_pointer_checks
26352
3.0104 1498
2.1178 gcc_base.none
note_stores
21306
2.4340 1950
2.7568 vmlinux
.pseries_dedicated_idle_sl\
eep
18059
2.0631 9186
12.9865 libc-2.13.so
memset
15867
1.8126 659
0.9316 gcc_base.none
init_alias_analysis
もう 1 つの興味深いパフォーマンス・カウンターとして、キャッシュ (L2 および L3 の両方) にか
かるアクセス負荷を監視します。以下の例では、perf を使用して、RHEL6.2 Linux システム GCC
でビルドされた SPECcpu2006 483.xalancbmk コンポーネント (「参考文献」を参照) をプロファイ
リングします。このコンポーネントはメモリー割り当てルーチンを駆使するため、メモリー・サ
ブシステムにかなりの負荷がかかることが予想されます。このプロファイリングを行うには、以
下の表 4 に記載するカウンターを OProfile で監視します。
表 4. POWER7 のキャッシュ/メモリー・アクセス・カウンター
カウンター
内容
PM_DATA_FROM_L2
デマンド・ロードによってローカルの L2 からプロセッサーのデータ・
キャッシュがリロードされた回数。
PM_DATA_FROM_L3
デマンド・ロードによってローカルの L3 からプロセッサーのデータ・
キャッシュがリロードされた回数。
PM_DATA_FROM_LMEM
このプロセッサーが配置されているのと同じモジュールに接続された
メモリーからプロセッサーのデータ・キャッシュがリロードされた回
数。
PM_DATA_FROM_RMEM
このプロセッサーが配置されているのとは異なるモジュールに接続さ
れたメモリーからプロセッサーのデータ・キャッシュがリロードされ
た回数。
プロファイリングによって、以下の結果が出力されます。
Linux on POWER のパフォーマンスを評価する
ページ 9 / 24
developerWorks®
ibm.com/developerWorks/jp/
リスト 8. 489.Xalancbmk ベンチマークに対する「opreport -l」の出力 (カウンター
PM_DATA_FROM_L2_GRP91 および PM_DATA_FROM_L3_GRP91)
CPU: ppc64 POWER7, speed 3550 MHz (estimated)
Counted PM_DATA_FROM_L2_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from the local L2 due to a demand load.) with a unit mask of 0x00 (No unit
mask) count 1000
Counted PM_DATA_FROM_L3_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from the local L3 due to a demand load.) with a unit mask of 0x00 (No unit
mask) count 1000
samples %
samples %
image name
app name
symbol name
767827
25.5750 7581
0.2525 gcc_base.none gcc_base.none bitmap_element_allocate
377138
12.5618 8341
0.2778 gcc_base.none gcc_base.none bitmap_operation
93334
3.1088 3160
0.1052 gcc_base.none gcc_base.none bitmap_bit_p
70278
2.3408 5913
0.1969 libc-2.13.so
libc-2.13.so
_int_free
56851
1.8936 22874
0.7618 oprofile
oprofile
/oprofile
47570
1.5845 2881
0.0959 gcc_base.none gcc_base.none rehash_using_reg
41441
1.3803 8532
0.2841 libc-2.13.so
libc-2.13.so
_int_malloc
リスト 9. 489.Xalancbmk ベンチマークに対する「opreport -l」の出力 (カウンター
PM_DATA_FROM_LMEM_GRP91 および PM_DATA_FROM_RMEM_GRP91)
Counted PM_DATA_FROM_LMEM_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from memory attached to the same module this proccessor is located on.) with
a unit mask of 0x00 (No unit mask) count 1000
Counted PM_DATA_FROM_RMEM_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from memory attached to a different module than this proccessor is located
on.) with a unit mask of 0x00 (No unit mask) count 1000
samples %
samples %
image name
app name
symbol name
1605
0.3344 0
0 gcc_base.none gcc_base.none bitmap_element_allocate
1778
0.3704 0
0 gcc_base.none gcc_base.none bitmap_operation
1231
0.2564 0
0 gcc_base.none gcc_base.none bitmap_bit_p
205
0.0427 0
0 libc-2.13.so
libc-2.13.so
_int_free
583
0.1215 327
100.000 oprofile
oprofile
/oprofile
0
0 0
0 gcc_base.none gcc_base.none rehash_using_reg
225
0.0469 0
0 libc-2.13.so
libc-2.13.so
_int_malloc
このプロファイル出力を解釈すると、L2 アクセス (PM_DATA_FROM_L2) のカウンター・サンプ
ルの合計値と相対値は、L3 デマンド・リロード (PM_DATA_FROM_L3) よりも遥かに大きいこと
から、キャッシュの負荷の大部分は L2 アクセスによるもので、デマンドによる L3 リロードはほ
とんどないことがわかります。キャッシュ・ミスが原因で L2 アクセスが CPU ストールを発生さ
せているのかどうかなど、詳しい情報を得るためには、(さらに多くのカウンターを監視すること
で) より包括的な分析を行わなければなりませんが、このプロファイルの例から、メイン・メモ
リー・アクセス (PM_DATA_FROM_LMEM イベント) はキャッシュ・アクセスに比べて大幅に少な
いという結論を引き出せます。さらに、リモート・アクセス (PM_DATA_FROM_RMEM イベント)
がないことが、リモート NUMA ノードのメモリー・アクセスは行われていないことを示していま
す。このように、ホットスポットとメモリー・アクセス・パターンを分析することで、最適化作
業の方向性が明らかになりますが、この例の場合、CPU ストールの真の原因を突き止めるには、
さらに詳しい分析が必要となります。ワークロードのホットスポットとメモリー・アクセス・パ
ターンを単純に明らかにするだけでは、CPU ストールを正確に突き止めることはできません。
より有効なパフォーマンス最適化戦略を考え出すには、OProfile ではなく perf ツールを使った
より詳しい分析が必要です。なぜなら、図 3 に示されている 22 の POWER7 CBM カウンターの多
くを同時に監視することで、より効果的なパフォーマンス最適化戦略が見えてくるからです。こ
れらのイベントの多くは、異なるグループに属します。つまり、OProfile を使用するには、同じ
Linux on POWER のパフォーマンスを評価する
ページ 10 / 24
ibm.com/developerWorks/jp/
developerWorks®
ワークロードを数多く実行しなければなりません。その一方、指定のカウンターが複数のグルー
プに属している場合、perf ツールはハードウェア・カウンターの監視を多重化します。この方法
では、結果の精度は低くなるものの、全体としての結果は期待する結果とそれほど変わらない傾
向があり、しかもプロファイリングにかかる時間が短縮されるという利点があります。
今度は、perf を使用して SPECcpu2006 483.xalancbmk コンポーネントをプロファイリングしてみ
ます。このコンポーネントをプロファイリングするには、リスト 10 のコマンドを実行します。
リスト 10. POWER7 CBM を生成する perf コマンド
$ /usr/bin/perf stat -C 0 -e r100f2,r4001a,r100f8,r4001c,r2001a,r200f4,r2004a,r4004a,
r4004e,r4004c,r20016,r40018,r20012,r40016,r40012,r20018,r4000a,r2001c,r1001c,r20014,
r40014,r30004 taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl > power7_cbm.dat
上記のコマンドにより、perf は、-c 引数で指定された CPU 上で、-e 引数で指定された 16 進コー
ドで表されたイベントを監視します。taskset を呼び出しているのは、CPU 番号 0 上でコンポー
ネントが排他的に実行されるようにするためです。ワークロード ./Xalan_base.none -v t5.xml
xalanc.xsl は、プロファイリング対象の別のアプリケーションに置き換えることもできます。プ
ロファイリングが完了すると、perf コマンドは 16 進コードで表されたイベントごとの合計カウン
トを簡単な表のような形で出力し、最後に合計経過秒数も出力します。
リスト 11. 489.Xalancbmk ベンチマークに対する「perf stat」の出力
Performance counter stats for 'taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl':
366,860,486,404
8,090,500,758
50,655,176,004
11,358,043,420
10,318,533,758
1,301,183,175,870
2,150,935,303
0
211,224,577,427
212,033,138,844
264,721,636,705
22,176,093,590
510,728,741,936
39,823,575,049
7,219,335,816
1,585,358
882,639,601,431
1,219,039,175
3,107,304
120,319,547,023
50,684,413,751
366,940,826,307
r100f2
r4001a
r100f8
r4001c
r2001a
r200f4
r2004a
r4004a
r4004e
r4004c
r20016
r40018
r20012
r40016
r40012
r20018
r4000a
r2001c
r1001c
r20014
r40014
r30004
[18.15%]
[13.65%]
[ 9.13%]
[ 9.11%]
[13.68%]
[18.22%]
[ 9.10%]
[13.65%]
[ 4.54%]
[ 4.54%]
[ 9.09%]
[ 9.11%]
[ 9.10%]
[ 9.07%]
[ 4.54%]
[ 9.08%]
[ 9.08%]
[ 9.08%]
[13.62%]
[ 9.09%]
[13.62%]
[18.16%]
461.057870036 seconds time elapsed
perf 出力を POWER7 CBM に照らし合わせて分析するための Python スクリプトが用意されていま
す (「ダウンロード」の power7_cbm.zip を調べてください)。このスクリプトは、収集された仮想
カウンターおよびハードウェア・カウンターからカウンター・メトリックを作成します。レポー
トを作成するには、リスト 12 のコマンドを実行します。
Linux on POWER のパフォーマンスを評価する
ページ 11 / 24
developerWorks®
ibm.com/developerWorks/jp/
リスト 12. POWER7 CBM Python スクリプトの呼び出し
$ power7_cbm.py power7_cbm.dat
すると、リスト 13 のような結果が出力されます。
リスト 13. 489.Xalancbmk ベンチマークに対する「power7_cbm.py」の出力
CPI Breakdown Model (Complete)
Metric
PM_CMPLU_STALL_DIV
PM_CMPLU_STALL_FXU_OTHER
PM_CMPLU_STALL_SCALAR_LONG
PM_CMPLU_STALL_SCALAR_OTHER
PM_CMPLU_STALL_VECTOR_LONG
PM_CMPLU_STALL_VECTOR_OTHER
PM_CMPLU_STALL_ERAT_MISS
PM_CMPLU_STALL_REJECT_OTHER
PM_CMPLU_STALL_DCACHE_MISS
PM_CMPLU_STALL_STORE
PM_CMPLU_STALL_LSU_OTHER
PM_CMPLU_STALL_THRD
PM_CMPLU_STALL_BRU
PM_CMPLU_STALL_IFU_OTHER
PM_CMPLU_STALL_OTHER
PM_GCT_NOSLOT_IC_MISS
PM_GCT_NOSLOT_BR_MPRED
PM_GCT_NOSLOT_BR_MPRED_IC_MISS
PM_GCT_EMPTY_OTHER
PM_1PLUS_PPC_CMPL
OVERHEAD_EXPANSION
Total
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
Value
49802421337.0
67578558649.0
2011413.0
7195240404.0
0.0
1209603592.0
22193968056.0
18190293594.0
261865838255.0
2001544985.0
202313206181.0
2025705.0
208356542821.0
2171796336.0
30895294057.0
9805421042.0
7823508357.0
11059314150.0
20292049774.0
365158978504.0
590057044.0
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
Percent
0.0
5.2
0.0
0.6
0.0
0.1
1.7
1.4
20.3
0.2
15.7
0.0
16.2
0.2
2.4
0.8
0.6
0.9
1.6
28.3
0.0
96.1
このレポートは、許容誤差の範囲内の統計値に基づいているため、最終的なパーセンテージは完
全に正確なわけではありません。許容誤差が大きいとしても、全 CPU ストールの約 20% は、デー
タのキャッシュ・ミスが原因となっています (PM_CMPLU_STALL_DCACHE_MISS)。完了した命令
の最終的なパーセンテージは、約 28% です (PM_1PLUS_PPC_CMPL)。
今後の最適化では、CPU ストールや GCT (Global Completion Table) のパーセンテージを下げ
ることで、完了した命令のパーセンテージが最大になるように努める必要があります。この
レポートに基づき、今度はもう 1 つの分析手段として、ストールが発生しているコードを
特定します。それには、perf record コマンドを使用します。このコマンドは、カウンター
の値そのもののパフォーマンスを追跡して、プロセスのバックトレースとのマップを作成
し、ハードウェア・イベントを最も多く生成したシンボルを特定できるようにします。こ
れは、OProfile が機能する仕組みと同様です。この例では、リスト 14 のコマンドを実行し
て、PM_CMPLU_STALL_DCACHE_MISS イベントを追跡します。
リスト 14. PM_CMPLU_STALL_DCACHE_MISS イベントに対して perf record を実行
する
$ /usr/bin/perf record -C 0 -e r20016 taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl
上記の perf コマンドにより、結果が格納されたデータ・ファイル (通常は「perf.dat」) が作成さ
れます。このファイルは、リスト 15 のperf report コマンドを使用してインタラクティブに読み取
ることができます。
Linux on POWER のパフォーマンスを評価する
ページ 12 / 24
ibm.com/developerWorks/jp/
developerWorks®
リスト 15. 489.Xalancbmk ベンチマークに対する perf report の出力
Events: 192
39.58%
11.46%
9.90%
7.29%
5.21%
5.21%
4.17%
2.08%
1.56%
1.56%
1.04%
[...]
raw 0x20016
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
Xalan_base.none
libc-2.13.so
Xalan_base.none
libc-2.13.so
libc-2.13.so
Xalan_base.none
Xalan_base.none
libc-2.13.so
[.]
[.]
[.]
[.]
[.]
[.]
[.]
[.]
[.]
[.]
[.]
xercesc_2_5::ValueStore::contains
xalanc_1_8::XStringCachedAllocator
xalanc_1_8::XStringCachedAllocator
xercesc_2_5::ValueStore::isDuplica
_int_malloc
__gnu_cxx::__normal_iterator<xa
__GI___libc_malloc
malloc_consolidate.part.4
xalanc_1_8::ReusableArenaBlock<xa
xalanc_1_8::ReusableArenaBlock<xa
__free
POWER7 CBM カウンターと perf report ツールを使用したこの分析に
より、最適化で重点的に取り組まなければならないのは、シンボル
xercesc_2_5::ValueStore::contains(xercesc_2_5::FieldValueMap const*) のメモリーおよびキャッ
シュ・アクセスであると考えられます。
この例は、実行可能な分析のほんの一部に過ぎません。POWER7 CBM から、データ・キャッ
シュ・ストールが CPU ストールの原因として高い割合を占めている一方、ロード・ストア・ユ
ニット (PM_CMPLU_STALL_LSU) と分岐ユニット (PM_CMPLU_STALL_BRU) の両方がストールの発
生元であることがわかります。これらのカウンターについては、さらに詳しい分析を行うことで
対処することができます。
事例研究
これから取り上げる事例研究では、ここまで述べたパフォーマンス評価戦略を三角関数の実装を
分析するために適用します。分析結果に基づき、最適化の可能性が明らかにされることになりま
す。この事例研究で使用する関数は、直角三角形の斜辺の長さとして定義される、ISO C の hypot
関数です。この関数は、C99 または POSIX.1-2001 で以下のように定義されています。
double hypot(double x, double y);
hypot() 関数は、sqrt(x*x+y*y) を返します。正常に処理が行われると、この関数は、隣辺 x お
よび対辺 y の直角三角形の斜辺の長さを返します。x または y が無限大の場合は、正の無限大
が返されます。x あるいは y の一方が NaN であり、他方の引数が無限大でない場合は、NaN
が返されます。結果がオーバーフローした場合は、範囲エラーが発生し、関数は対応する
HUGE_VAL、HUGE_VALF、または HUGE_VALL を返します。両方の引数が非正規数であり、結果
も非正規数となる場合には、範囲エラーが発生し、正しい結果が返されます。
このアルゴリズムは単純そうに思えますが、無限大と NaN を処理する FP (Floating-Point: 浮動小数
点) 引数、そして FP 演算に関連するオーバーフロー/アンダーフローによって、パフォーマンスに
影響を及ぼす難題が生じます。GNU C ライブラリー (「参考文献」を参照) には、hypot の実装が
ソース・ツリーの sysdeps/ieee754/dbl-64/e_hypot.c に用意されています。
注: このサンプル・コードのライセンス情報は、「付録」に記載されています。
リスト 16. デフォルトの GLIBC hypot ソース・コード
double __ieee754_hypot(double x, double y)
Linux on POWER のパフォーマンスを評価する
ページ 13 / 24
developerWorks®
ibm.com/developerWorks/jp/
{
double a,b,t1,t2,y1,y2,w;
int32_t j,k,ha,hb;
GET_HIGH_WORD(ha,x);
ha &= 0x7fffffff;
GET_HIGH_WORD(hb,y);
hb &= 0x7fffffff;
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
SET_HIGH_WORD(a,ha);
/* a <- |a| */
SET_HIGH_WORD(b,hb);
/* b <- |b| */
if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
k=0;
if(ha > 0x5f300000) {
/* a>2**500 */
if(ha >= 0x7ff00000) {
/* Inf or NaN */
u_int32_t low;
w = a+b;
/* for sNaN */
GET_LOW_WORD(low,a);
if(((ha&0xfffff)|low)==0) w = a;
GET_LOW_WORD(low,b);
if(((hb^0x7ff00000)|low)==0) w = b;
return w;
}
/* scale a and b by 2**-600 */
ha -= 0x25800000; hb -= 0x25800000; k += 600;
SET_HIGH_WORD(a,ha);
SET_HIGH_WORD(b,hb);
}
if(hb < 0x20b00000) {
/* b < 2**-500 */
if(hb <= 0x000fffff) {
/* subnormal b or 0 */
u_int32_t low;
GET_LOW_WORD(low,b);
if((hb|low)==0) return a;
t1=0;
SET_HIGH_WORD(t1,0x7fd00000);
/* t1=2^1022 */
b *= t1;
a *= t1;
k -= 1022;
} else {
/* scale a and b by 2^600 */
ha += 0x25800000;
/* a *= 2^600 */
hb += 0x25800000;
/* b *= 2^600 */
k -= 600;
SET_HIGH_WORD(a,ha);
SET_HIGH_WORD(b,hb);
}
}
/* medium size a and b */
w = a-b;
if (w>b) {
t1 = 0;
SET_HIGH_WORD(t1,ha);
t2 = a-t1;
w = __ieee754_sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
} else {
a = a+a;
y1 = 0;
SET_HIGH_WORD(y1,hb);
y2 = b - y1;
t1 = 0;
SET_HIGH_WORD(t1,ha+0x00100000);
t2 = a - t1;
w = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
}
if(k!=0) {
u_int32_t high;
t1 = 1.0;
GET_HIGH_WORD(high,t1);
Linux on POWER のパフォーマンスを評価する
ページ 14 / 24
ibm.com/developerWorks/jp/
developerWorks®
SET_HIGH_WORD(t1,high+(k<<20));
return t1*w;
} else return w;
}
上記コードでは、FP から INT へのビット単位の変換が数多く実行されるアルゴリズムとなってい
ることが主な原因で、かなり複雑な実装となっています。この実装で前提となっているのは、比
較や乗算などの特定の FP 演算は、浮動小数点命令を使用する場合の方が固定小数点命令を使用す
る場合よりもコストが高くなる、ということです。これは、一部のアーキテクチャーには当ては
まりますが、Power Architecture には当てはまりません。
この実装を評価する最初のステップは、プロファイリング可能なベンチマークを作成することで
す。この例で評価するのは、2 つの引数を取り、(内部関数呼び出しや別のパスがない) 単純なアル
ゴリズムを使用する関数に過ぎません。したがって、関数を評価するために作成するベンチマー
クも単純なものにすることができます (「ダウンロード」の hypot_bench.tar.gz を参照)。このベン
チマークをパフォーマンス評価の一部として、最適化によってアルゴリズムの実行が高速になる
ように、あるいはワークロード・パフォーマンス全体に影響を及ぼすアルゴリズムの重要部分が
最適化によって高速に実行されるようにしてください。このような合成ベンチマークは、この関
数の通常の使用方法を表すものでなければなりません。そして最適化の取り組みでは、リソース
も時間も大量に費やす傾向があるため、最も一般的な使用ケースや最も一般的なものとして想定
される振る舞いに焦点を絞る必要があります。使用されることが少ないプログラムのコードを最
適化しようとすると、リソースを浪費する結果になりがちです。
この事例研究は、1 つの関数のパフォーマンスを分析する例なので、ホットスポット分析は省略
して、CMB 分析に焦点を絞ることができます。hypot_bench.c のベンチマークで perf を使用する
と、リスト 17 の CBM 情報が出力されます、
リスト 17. hypot ベンチマークに対する「power7_cbm.py」の出力
CPI Breakdown Model (Complete)
Metric
PM_CMPLU_STALL_DIV
PM_CMPLU_STALL_FXU_OTHER
PM_CMPLU_STALL_SCALAR_LONG
PM_CMPLU_STALL_SCALAR_OTHER
PM_CMPLU_STALL_VECTOR_LONG
PM_CMPLU_STALL_VECTOR_OTHER
PM_CMPLU_STALL_ERAT_MISS
PM_CMPLU_STALL_REJECT_OTHER
PM_CMPLU_STALL_DCACHE_MISS
PM_CMPLU_STALL_STORE
PM_CMPLU_STALL_LSU_OTHER
PM_CMPLU_STALL_THRD
PM_CMPLU_STALL_BRU
PM_CMPLU_STALL_IFU_OTHER
PM_CMPLU_STALL_OTHER
PM_GCT_NOSLOT_IC_MISS
PM_GCT_NOSLOT_BR_MPRED
PM_GCT_NOSLOT_BR_MPRED_IC_MISS
PM_GCT_EMPTY_OTHER
PM_1PLUS_PPC_CMPL
OVERHEAD_EXPANSION
Total
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
Value
8921688.0
13953382275.0
24380128688.0
33862492798.0
0.0
275057010.0
173439.0
902838.0
15200163.0
1837414.0
94866270200.0
569036.0
10470012464.0
-73357562.0
7140295432.0
3586554.0
1008950510.0
795943.0
42488384303.0
53138626513.0
30852715.0
Linux on POWER のパフォーマンスを評価する
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
:
Percent
8.7
5.0
8.7
12.0
0.0
0.1
0.0
0.0
0.0
0.0
33.7
0.0
3.7
0.0
2.5
0.0
0.4
0.0
15.1
18.9
0.0
108.7
ページ 15 / 24
developerWorks®
ibm.com/developerWorks/jp/
プロファイル分析から、CPU ストールの大部分、つまりパフォーマンス損失の主な原因は、ロー
ド・ストア・ユニット (LSU ― PM_CMPLU_STALL_LSU_OTHER カウンター) であることがわかり
ます。LSU にはさまざまなカウンターが関連付けられていますが、CPUストールを分析する際に
焦点となるのは、パフォーマンスの低下に関連するカウンターです。POWER でパフォーマンスの
低下を示すカウンターは、ロード・ヒット・ストア (LHS) ハザードに関連します。LHS ハザード
は、CPU がデータをあるアドレスに書き込んだ直後にそのデータをリロードしようとすると発生
する、大規模なストールです。次のステップでは、LHS ハザードがこの特定のアルゴリズムで発
生しているのかどうかを調べるために、最初に PM_LSU_REJECT_LHS イベント (16 進のイベント・
コード「c8ac」) を確認します (リスト 18 を参照)。
リスト 18. POWER7 のイベント PM_LSU_REJECT_LHS に対して perf record を実行
し、結果を perf report で表示する
$ perf record -C 0 -e rc8ac taskset -c 0 ./hypot_bench_glibc
$ perf report
Events: 14K raw 0xc8ac
79.19% hypot_bench_gli libm-2.12.so
[.] __ieee754_hypot
10.38% hypot_bench_gli libm-2.12.so
[.] __hypot
6.34% hypot_bench_gli libm-2.12.so
[.] __GI___finite
このプロファイル出力から、シンボル __ieee754_hypot が PM_LSU_REJECT_LHS イベントの
大多数を生成していることがわかります。次に、どの命令がこのイベントを生成しているか
を特定するために、コンパイラーが生成したアセンブリー・コードを調査します。シンボル
__ieee754_hypot を展開してアセンブリー・コードを表示し、各コードの実行に要した時間の割
合を表示するには、perf annotate で __ieee754_hypot シンボルを指定して実行します。これによ
り、リスト 19 の出力が表示されます。
リスト 19. POWER7 のイベント PM_LSU_REJECT_LHS に対して perf annotate
__ieee754_hypot を実行する
0.00
0.00
0.00
13.62
0.00
10.82
0.23
17.54
0.00
0.00
0.00
8.46
[...]
:
:
:
:
:
:
:
:
:
:
:
:
:
00000080fc38b730 <.__ieee754_hypot>:
80fc38b730:
7c 08 02 a6
mflr
80fc38b734:
fb c1 ff f0
std
80fc38b738:
fb e1 ff f8
std
80fc38b73c:
f8 01 00 10
std
80fc38b740:
f8 21 ff 71
stdu
80fc38b744:
d8 21 00 70
stfd
80fc38b748:
e9 21 00 70
ld
80fc38b74c:
d8 41 00 70
stfd
80fc38b750:
79 29 00 62
rldicl
80fc38b754:
e9 61 00 70
ld
80fc38b758:
e8 01 00 70
ld
80fc38b75c:
d8 21 00 70
stfd
r0
r30,-16(r1)
r31,-8(r1)
r0,16(r1)
r1,-144(r1)
f1,112(r1)
r9,112(r1)
f2,112(r1)
r9,r9,32,33
r11,112(r1)
r0,112(r1)
f1,112(r1)
この実装は、コードの最初のほうでマクロ GET_HIGH_WORD を使用して、後のほうで行うビット
単位の演算のために「浮動小数点数」を「整数」に変換します。このマクロは、GLIBC の math/
math_private.h 内でリスト 20 のコードを使用して定義されています。
Linux on POWER のパフォーマンスを評価する
ページ 16 / 24
ibm.com/developerWorks/jp/
developerWorks®
リスト 20. GET_HIGH_WORD マクロの定義
#define GET_HIGH_WORD(i,d)
do {
ieee_double_shape_type gh_u;
gh_u.value = (d);
(i) = gh_u.parts.msw;
} while (0)
\
\
\
\
\
このマクロで LHS ストールを発生させている原因として考えられるのは、浮動小数点数の属性を
内部値に読み込んでから、それを変数 i に読み出す演算です。POWER7 プロセッサーには、浮動小
数点レジスターの内容をビット単位で固定小数点レジスターに移すためのネイティブ命令があり
ません。POWER でそのネイティブ命令の代わりの方法となるのは、ストア命令によって浮動小数
点レジスター内の浮動小数点数をメモリーにストアしてから、同じメモリー位置を固定小数点 (汎
用) レジスターにロードすることです。メモリー・アクセスは (L1 データ・キャッシュにアクセス
する場合でも) レジスター操作よりも遅いため、ストアが後続のロードを完了するまで、CPU のス
トールが発生します。
注: 「POWER ISA Version 2.06 (POWER7)」(「参考文献」を参照) に詳細が説明されています。
ほとんどの場合、パフォーマンス・カウンター (PC) イベントによってトリガーされる割り込み
では、実行中の命令に近い命令の PC が保存されるため、アセンブリー・アノテーションが完
全には正確なものでなくなる可能性があります。こうした振る舞いが発生するのを抑えるため
に、POWER4 以降では、marked という限定されたパフォーマンス・カウンター一式が用意されて
います。これを利用した場合、命令にマークが付けられると、その命令が時間フレームあたりに
生成するイベント数は少なくなりますが、命令の PC は正確になるはずです。そのため、アセン
ブリー・アノテーションも正確になります。opcontrol -l によって取得される OProfile カウン
ターのリストでは、マークが付けられたイベントには PM_MRK というプレフィックスが付けられ
ます。
分析をダブルチェックするために、PM_MRK_LSU_REJECT_LHS カウンターを監視しま
す。PM_MRK_LSU_REJECT_LHS と PM_LSU_REJECT_LHS の両方のカウンターで、同じパフォーマ
ンス・イベントを監視してください。marked カウンター (PM_MRK_LSU_REJECT_LHS) が時間フ
レームあたりに生成するイベント数は少ないはずですが、アセンブリー・アノテーションの精度
は高くなるはずです (リスト 21 を参照)。
リスト 21. POWER7 のイベント PM_MRK_LSU_REJECT_LHS に対して perf record を
実行し、結果を perf report で表示する
$ perf record -C 0 -e rd082 taskset -c 0 ./hypot_bench_glibc
$ perf report
Events: 256K raw 0xd082
64.61% hypot_bench_gli libm-2.12.so
[.] __ieee754_hypot
35.33% hypot_bench_gli libm-2.12.so
[.] __GI___finite
続いて、perf annotate __ieee754_hypot を実行することで、リスト 22 のアセンブリー・アノテー
ションが生成されます。
Linux on POWER のパフォーマンスを評価する
ページ 17 / 24
developerWorks®
ibm.com/developerWorks/jp/
リスト 22. POWER7 のイベント PM_MRK_LSU_REJECT_LHS に対して perf annotate
__ieee754_hypot を実行する
:
[...]
1.23
0.00
32.66
[...]
0.00
0.00
0.00
61.72
[...]
00000080fc38b730 <.__ieee754_hypot>:
:
:
:
80fc38b7a8:
80fc38b7ac:
80fc38b7b0:
c9 a1 00 70
f8 01 00 70
c8 01 00 70
lfd
std
lfd
f13,112(r1)
r0,112(r1)
f0,112(r1)
:
:
:
:
80fc38b954:
80fc38b958:
80fc38b95c:
80fc38b960:
f8
e8
79
c9
std
ld
rldimi
lfd
r0,112(r1)
r0,0(r11)
r0,r8,32,0
f11,112(r1
01
0b
00
61
00
00
00
00
70
00
0e
70
別のシンボルにも、生成されたイベントの約 35% に同様の振る舞いが見られます (リスト 23 を参
照)。
リスト 23. perf report のもう 1 つの注目点
:
0.00 :
100.00 :
00000080fc3a2610 <.__finitel>>
80fc3a2610:
d8 21 ff f0
80fc3a2614:
e8 01 ff f0
stfd
ld
f1,-16(r1)
r0,-16(r1)
この情報に基づくと、これらのストールを排除するための最適化手法として考えられるのは、FP
から INT への変換をなくすことです。POWER プロセッサーには、高速かつ効率的な浮動小数点
実行ユニットがあるため、これらの計算を固定小数点命令で行う必要はありません。POWER が
GLIBC で現在使用しているアルゴリズム (sysdeps/powerpc/fpu/e_hypot.c) は、LHS ストールを完全
になくすために、FP 演算のみを使用しています。その結果、アルゴリズムはリスト 24 のように
大幅に単純化されます。
リスト 24. PowerPC の GLIBC hypot ソース・コード
double
__ieee754_hypot (double x, double y)
{
x = fabs (x);
y = fabs (y);
TEST_INF_NAN (x, y);
if (y > x)
{
double t = x;
x = y;
y = t;
}
if (y == 0.0 || (x / y) > two60)
{
return x + y;
}
if (x > two500)
{
x *= twoM600;
y *= twoM600;
return __ieee754_sqrt (x * x + y * y) / twoM600;
}
if (y < twoM500)
{
if (y <= pdnum)
{
Linux on POWER のパフォーマンスを評価する
ページ 18 / 24
ibm.com/developerWorks/jp/
developerWorks®
x *= two1022;
y *= two1022;
return __ieee754_sqrt (x * x + y * y) / two1022;
}
else
{
x *= two600;
y *= two600;
return __ieee754_sqrt (x * x + y * y) / two600;
}
}
return __ieee754_sqrt (x * x + y * y);
}
TEST_INF_NAN マクロにも、簡単な最適化を行います。このマクロは、数字が NaN または INFINITY
であるかどうかを調べてから、その後の FP 演算を開始します (これは、NaN と INFINITY での演算
によって、この関数の仕様では許可されない FP 例外が発生する可能性があるためです)。POWER7
では、isinf および isnan 関数呼び出しはコンパイラーによって FP 命令に最適化されるため、追
加の関数呼び出しは生成されません。それよりも古いプロセッサー (POWER6 以前) では、それぞ
れの関数呼び出しが生成されます。この最適化は基本的に同じ実装ですが、関数呼び出しを避け
るためにインライン化されています。
最後に両方の実装を比較するために、以下の単純なテストを行います。新しいアルゴリズムを使
用した場合と使用しない場合とで GLIBC を再コンパイルして、各ベンチマークの実行時間の合計
を比較します。デフォルトの GLIBC 実装の結果は、リスト 25 のとおりです。
リスト 25. デフォルトの GLIBC hypot でのベンチマーク
$ /usr/bin/time ./hypot_bench_glibc
INF_CASE
: elapsed time: 14:994339
NAN_CASE
: elapsed time: 14:707085
TWO60_CASE
: elapsed time: 12:983906
TWO500_CASE
: elapsed time: 10:589746
TWOM500_CASE
: elapsed time: 11:215079
NORMAL_CASE
: elapsed time: 15:325237
79.80user 0.01system 1:19.81elapsed 99%CPU (0avgtext+0avgdata 151552maxresident)k
0inputs+0outputs (0major+48minor)pagefaults 0swaps
最適化したバージョンの結果をリスト 26 に記載します。
リスト 26. 最適化した GLIBC hypot でのベンチマーク
$ /usr/bin/time ./hypot_bench_glibc
INF_CASE
: elapsed time: 4:667043
NAN_CASE
: elapsed time: 5:100940
TWO60_CASE
: elapsed time: 6:245313
TWO500_CASE
: elapsed time: 4:838627
TWOM500_CASE
: elapsed time: 8:946053
NORMAL_CASE
: elapsed time: 6:245218
36.03user 0.00system 0:36.04elapsed 99%CPU (0avgtext+0avgdata 163840maxresident)k
0inputs+0outputs (0major+50minor)pagefaults 0swaps
最終的なパフォーマンスの改善は 100% を超え、ベンチマークの時間は半分に縮小されています。
Linux on POWER のパフォーマンスを評価する
ページ 19 / 24
developerWorks®
ibm.com/developerWorks/jp/
まとめ
ハードウェア・カウンターのプロファイリングによるパフォーマンス評価は、特定のプロセッ
サーでのワークロードの振る舞いを理解し、パフォーマンスの最適化をするとよい対象を知る手
掛かりをつかむ上で強力なツールです。最新の POWER7 プロセッサーでは、何百ものパフォーマ
ンス・カウンターを使用することができます。この記事ではワークロードと CPU ストールを対応
付ける単純なモデルを紹介しました。また、POWER7 CBM を理解するのは多少複雑な作業である
ため、Linux でその作業を単純化するツールについても説明しました。パフォーマンス評価の戦
略では、ホットスポットを見つける方法、アプリケーションのメモリー・パターンを理解する方
法、POWER7 CBM を使用する方法に焦点を絞りました。そして最後に、GLIBC 内で最近行われた
最適化を三角関数に対して適用する例を用いて、パフォーマンス分析を使用してコードを最適化
する方法を説明しました。
付録
この記事を複製、配布、変更する許可は、GNU Free Documentation License, Version 1.3 の条件の
下に与えられています。変更不可部分、表カバー・テキスト、裏カバー・テキストは存在しま
せん。ライセンスのコピーは、http://www.gnu.org/licenses/fdl-1.3.txt から入手することができま
す。
Linux on POWER のパフォーマンスを評価する
ページ 20 / 24
ibm.com/developerWorks/jp/
developerWorks®
ダウンロード
内容
ファイル名
サイズ
GLIBC hypot benchmark
hypot_bench.tar.gz
6KB
Python script to format perf output
power7_cbm.zip
2KB
Linux on POWER のパフォーマンスを評価する
ページ 21 / 24
developerWorks®
ibm.com/developerWorks/jp/
参考文献
学ぶために
• 「Modern Microprocessors - A 90 Minute Guide」で、最近のマイクロプロセッサーでのプロ
セッサーの動作についての詳細を読んでください。
• 「Comprehensive PMU Event Reference POWER7」は、POWER7 の包括的な PMU リファレン
スです (「参考文献」を参照)。
• OProfile の包括的なガイドとしては、「Identify performance bottlenecks with OProfile for
Linux on POWER」(John Engel 著、developerWorks、2005年5月) を読んでください (ただ
し、POWER7 に応じて更新されてはいません)。
• IBM の Wiki「Using perf on POWER7 systems」を調べてください。perf の包括的ガイドになり
ます (ただし、POWER7 に対応するように更新されてはいません)。
• SPECcpu2006 483.xalancbmk コンポーネントについての説明を読んでください。
• POWER ISA 2.06 (POWER7) について読んでください。
• 最近のプロセッサーのパイプライン化および命令レベルの並列性、命令の依存関係、分岐予
測、および CPU アーキテクチャーに関するその他のトピックについて、教訓的な情報を満載
した記事を読んでください。
• POWER7 の包括的なイベント・リファレンスを読んで、ハードウェア・スレッドごとの組み
込みパフォーマンス監視ユニットについて詳しく学んでください。
• POWER7 命令セット・アーキテクチャー、PowerISA 2.06 の詳細を学んでください。
• OProfile for Linux on POWER でパフォーマンス・ボトルネックを突き止めてください。
• POWER7 システムでの perf の詳細な使用方法について読んでください。
• GLIBC ソース・コードを調べてください。
• この記事で使用しているサンプル・コードについては、SPECCPU2006 資料を調べてくださ
い。
• developerWorks Linux ゾーンで、Linux 開発者および管理者向けのハウツー記事とチュートリ
アル、そしてダウンロード、ディスカッション、フォーラムなど、豊富に揃った資料を探し
てください。
• developerWorks Open source ゾーンには、オープソースのツールおよびオープンソース技術
の使用に関する情報が豊富に揃っています。
• さまざまな IBM 製品や IT 業界のトピックに焦点を絞った developerWorks の Technical events
and webcasts で最新情報を入手してください。
• 無料の developerWorks Live! briefing に参加して、IBM の製品およびツールについての情報や
IT 業界の動向についての情報を迅速に把握してください。
• developerWorks の on-demand demos で、初心者向けの製品のインストールとセットアップ
から、熟練開発者向けの高度な機能に至るまで、さまざまに揃ったデモを見てください。
• Twitter で developerWorks をフォローするか、developerWorks で Linux に関するツイートの
フィードに登録してください。
製品や技術を入手するために
• OProfile について、このプロジェクトの Web サイトで詳細を学んでください。
• perf ツールの詳細を学んでください。このツールのコードは Linux カーネル・ソース内で保
守されています。
• libpfm4 プロジェクトのサイトで、perf に固有の POWER7 コードを調べてください。
Linux on POWER のパフォーマンスを評価する
ページ 22 / 24
ibm.com/developerWorks/jp/
developerWorks®
• GNU C ライブラリーについては、このプロジェクトのページを参照してください。
• Advance Toolchain for Linux on POWER について調べてください。これは、IBM ハードウェア
の機能を使いやすくする目的でカスタマイズされた無料のソフトウェア・アプリケーション
開発製品のコレクションです。
• ご自分に最適な方法で IBM 製品を評価してください。評価の方法としては、製品の試用版
をダウンロードすることも、オンラインで製品を試してみることも、クラウド環境で製品
を使用することもできます。また、SOA Sandbox では、数時間でサービス指向アーキテク
チャーの実装方法を効率的に学ぶことができます。
議論するために
• ディスカッション・フォーラムに参加してください。
• IBM フォーラムで、IBM Advance Toolchain 5.0 for POWER についてのディスカッションに参
加し、リソースを探してください。
• developerWorks ブログから developerWorks コミュニティーに参加してください。
• developerWorks コミュニティーに参加してください。ここでは他の developerWorks ユー
ザーとのつながりを持てる他、開発者によるブログ、フォーラム、グループ、ウィキを調べ
ることができます。
Linux on POWER のパフォーマンスを評価する
ページ 23 / 24
developerWorks®
ibm.com/developerWorks/jp/
著者について
Adhemerval Zanella Netto
Adhemerval Netto は、IBM Linux Technology Center に勤務する熟練のソフトウェ
ア・エンジニアです。現在、Power Architecture のパフォーマンス分析およびツール
チェーン開発に取り組んでいます。彼は、spec.org で Linux でのさまざまな Power パ
フォーマンス・レポートを担当し、オープンソース・ソフトウェア (glibc) に貢献し
ています。
Ryan S. Arnold
Ryan Arnold は、IBM Linux Technology Center の IBM Advisory Software Engineer で
す。GNU ツールチェーンの統合、および Linux システム・ライブラリーの開発で経
験を積んでいます。彼は、GLIBC の Power Architecture の保守者であり、Libdfp の
中心的ライブリー保守者です。また、「Power Architecture 32-bit Application Binary
Interface Supplement 1.0」の共著者でもあります。
© Copyright IBM Corporation 2012
(www.ibm.com/legal/copytrade.shtml)
商標
(www.ibm.com/developerworks/jp/ibm/trademarks/)
Linux on POWER のパフォーマンスを評価する
ページ 24 / 24