ラベル ハードウェアカウンタ の投稿を表示しています。 すべての投稿を表示
ラベル ハードウェアカウンタ の投稿を表示しています。 すべての投稿を表示

2009年9月30日水曜日

RDMSR / WRMSR in C

MSR(Model Specific Register)を読み書きするための命令
どちらも実行できるのは特権モード(ring 0)のみ

これらを C の中で使うには gcc インラインアセンブラを用いればOK

#ちなみにこのへんの記述は perfctr では /usr/include/asm-x86/msr.h にありますね

●インラインアセンブラ表記法
asm volatile ("アセンブラテンプレート"
: "出力オペランド"
: "入力オペランド"
: "アセンブラの実行で変更されてしまうもの");

出力オペランドは "=a" (出力先変数),
入力オペランドは "a" (入力) のように表記する.
ここで,各レジスタは以下のように表記する.
"a" eax
"b" ebx
"c" ecx
"d" edx
"A" edx:eax(上位bitにedx,下位bitにeax)
"g" gccが適当なレジスタに割り当てる


●RDMSR
ecx レジスタに MSR のアドレスを指定すると,edx:eax レジスタに MSR の内容を読み込む(上位 32bit が edx ,下位 32bit が eax に入る)
e.g.
asm volatile("rdmsr" : "=a"(low), "=d"(high) : "c"(msr_addr));
asm volatile("rdmsr" : "=A"(val) : "c"(msr_addr));

●WRMSR
ecx レジスタに指定した MSR のアドレスに,edx:eax レジスタの内容を書き込む(〃)
e.g.
asm volatile("wrmsr" : : "c"(msr_addr), "=a"(low), "=d"(high) : "memory");
asm volatile("wrmsr" : : "c"(msr_addr), "=A"(val) : "memory");


参照ページ:
ほげほげまん: gccインラインアセンブラ
ほげほげまん: RDMSR / WRMSR

ほげほげまんめっちゃ分かりやすい.お世話になってますw

2008年11月17日月曜日

Linux Performance Counters Driver

PAPI(前日記参照)を用いてシステムワイドな値がとれないということが発覚しました…
PAPIはあくまでもプログラムごとのハードウェアカウンタの値を見るもので,このプログラムだとキャッシュミスが多いな…などといったことを発見し,プログラムのチューンアップを行うもののようです.

しかし,PAPIをインストールした際に,kernelにパッチをあてた,
Linux Performance Counters Driver(perfctr)を利用すれば,システムワイドな値がとれる様子.

しかしこれ,ドキュメントがない!
ので,ソースを見て解読するしかないっぽいです

とりあえずサンプルコードはあるので,真似して使えるようにならねば.

2008年11月4日火曜日

PAPIのインストール

PAPI:Performance Application Programming Interface
ハードウェアカウンタを見ることができるAPIです.

まずはここから最新版をダウンロード.

INSTALLガイドを見ると,カーネルにパッチをあてる必要があるようで.
(Linux/x86)

●kernel●
まずは,カーネルをダウンロード.
パッチのバージョンと合うように,今回は2.6.25をダウンロード.
/usr/src/kernels内に展開.
そのディレクトリに移動.
shell> cp ../linux-2.6.23/.config .
-今まで使っていた.configファイルをディレクトリ内にコピー
shell> make mrproper
 -お掃除
shell> papi-3.6.2/src/perfctr-2.6.x/update-kernel
-perfctr(Performance Monitoring Counters Driver)をカーネル内に入れるためのパッチあて
shell> make oldconfig
-さっきコピーしたconfigファイルを引き継ぐ
shell> make menuconfig
-更にinstallガイドの沿って設定を行う("PERCESSOR TYPE AND FEATURES"内のPerformance MoniteringをMにして,中のものに全てチェックをつけるetc)
shell> make bzImage
 -bzImageというカーネルイメージを作成
shell> make modules
-モジュール作成
shell> make modules_install
-/lib/modules/下にモジュールがインストールされる.
shell> make install
-/boot/以下にカーネルイメージなどが作成される.

ブートローダの設定
/etc/grub.confのdefaultの値を1から0に書き換えることで,デフォルトで起動するカーネルイメージを変更できる.
(/etc/grub.confに新しく入れたカーネルのバージョンが書き足されているため,default値は,0から1に変わっているので)

で,reboot!!
2.6.25で起動します.

●Dynamic /dev (udev)●
Linuxのいろんなバージョンに適合させるための作業
papi-3.6.2/src/perfctr-2.6.x/下で行います
shell> cp etc/perfctr.rules /etc/udev/rules.d/99-perfctr.rules
-perfctrがカーネルにロードされたときに,udevが,全ユーザのアクセスできる/dev/perfctrを作成するためのルールを追加
shell> cp etc/perfctr.rc /etc/rc.d/init.d/perfctr
 -カーネルがperfctrモジュールを自動で呼ぶことを可能とするためのスクリプトを追加
shell> chmod 755 /etc/rc.d/init.d/perfctr
shell> /sbin/chkconfig --add perfctr
 -perfctrという新しいシステムサービスを追加(詳細は@IT)

rebootする.

shell> papi-3.6.2/src/perfctr-2.6.x/examples/perfex/perfex -i
とすると,
なんだかOKそうな値がちゃんと出ました!!
PerfCtr Info:
abi_version 0x05020501
driver_version 2.6.35 DEBUG
cpu_type 18 (Intel Core 2)
cpu_features 0x7 (rdpmc,rdtsc,pcint)
cpu_khz 2394142
tsc_to_cpu_mult 1
cpu_nrctrs 5
cpus [0,1,2,3], total: 4
cpus_forbidden [], total: 0

基礎作り終了.

●PAPIインストール●
papi-3.6.2/src/下で行う
shell> ./configure
shell> make
shell> make test
-テストを1つ行う.良い結果が出たら次へ.
shell> make fulltest

PAPIインストール終了ー!
次は,doc/下のUSER'S GUIDE見たりして使い方のお勉強です.

2008年11月3日月曜日

Hardware Counter Driven On-the-Fly Request Signatures

ASPLOS'08の,Kai Shenさんたちの論文です.
ハードウェアカウンタの値を用いて実行中のリクエストを早期識別しちゃおう!というスゴイ話.
ゼミでやったので詳しめにまとめ.
(先輩方に色々フォローしてもらって勉強になりました!もっとしっかり読めるようになりたい)

●背景&問題点●
OSは,実行時のワークロードのプロパティを知ることで,より良いスケジューリングが可能になったり,コストを抑えたNWサービスが可能となる.
しかし,現状では,過去のリクエストからワークロードのプロパティを予測する手法がとられている.
この手法では,入力パターンが多く,実行時の状態が変化するワークロードの予測を当てることは難しい.

●提案●
サーバリクエストを実行中の早い段階で識別し,プロパティを予測しよう.
 -プロパティとは:メモリ使用量,CPU使用量,I/O発行量など
この,リクエストの識別は,ハードウェアカウンタの値を数個組み合わせてシグネチャとすることで可能となる.

●ハードウェアカウンタの組み合わせ●
レジスタにマップできるハードウェアカウンタの数はプロセッサにより限られているため,数個選ぶ必要がある.
選ぶ際には,以下の3つに注意.
1.正規化の種類(time-based or progress-based)
 全てのハードウェアカウンタを両方で正規化し,相関係数が高い値になった方を採用する.
 調査の結果,イベントカウント数が関わる値はprogress-based,持続時間が関わる値はtime-basedが適していることが分かった.
2.環境の影響
 リクエストを並列に実行した場合の相関係数は,全ハードウェアカウンタの値で低くなっているが,その中でもなるべく影響を受けないもの(*)を採用する.(L2Refferenceなど)
 *L2キャッシュ・メモリアクセスに関わる値は,コンテキストスイッチの影響を大きく受けるため,避けたい
 *L1キャッシュ・トレースキャッシュ・TLBのイベント関連は,ハイパースレッディングの機能を持つ場合に,これらの機能を共有するために不安定な値をとるため,避けたい
3.アプリケーションによる違い
 サーバアプリケーションの種類によって効果のあるハードウェアカウンタが異なるため,それぞれのアプリケーションごとに適切なハードウェアカウンタを選ぶ必要がある.

●値の収集とリクエスト識別●
1.ハードウェアカウンタの値はインクリメントされるため,定期的に値を取り出し,その差を収集する.
2.収集したいくつかの値をシグネチャとし,そのリクエストのプロパティとの対応表を作成する.
3.対応表の値と実行中のハードウェアカウンタの値の差により,リクエストを識別する.
 -リクエスト実行してからある一定時間で識別を行う方法と,対応するリクエストが見つかるまで時間を増やして識別を行う方法の2種類がある.

●実験●
4つのサーバアプリケーションで実験した.
―TPC-C,TPC-H,RUBiS,Index search(最初の3つはCPU-bound, その他はI/O-bound)
CPU使用量,I/Oサイズの予測の正確性を評価したところ,並列実行でも7%,3%,20%,40%と非常に低いミスを実現.
RUBiSやIndexsearchは,初めに同じような経路を辿るために他と比べて識別が難しくなっているが,TPCの2つに関しては,リクエスト実行の非常に早い段階で正確な識別ができている.

●応用例●
1.効果的なスケジューリングの実現
 この提案手法を用いてレディータスク内で最も残り時間が短いタスクをキューの先頭にもってくることで(SRPTスケジューリング),デフォルトのスケジュールに比べ70%以上応答時間の削減に成功した.
2.異例なリクエストの検出
 似たリクエストでクラスを作り,リクエストを早期に分類することで,SQLインジェクションなどの異例なリクエストの検出が行えた.


…ちょっとはしょったつもりが,詳しく書きすぎたかもw
長いw