実行した命令数をカウントする

2015年10月27日

一週間で三回ぐらい聞かれたので知っている範囲で書いておきます。

パフォーマンスカウンタの値をとる

全命令をカウントするINST_RETIREDがありますが、もう少し詳細な値も取れます。

http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html の、Volume 3B: part2 Chapter19 から対応するCPUを探して、欲しいカウンタを探してみましょう。

UOPS_EXECUTED_PORT.PORT_{0,1,..} (Event=0xb1, Umask=0x01) など
実行ポートごとに取得できます。uops単位なのでx86命令単位より増える可能性があります
UOPS_DISPATCHED_PORT.PORT_{0,1,..} (Event=0xa1, Umask=0x01) など
executedとの違いは…よくわからないです
FP_ARITH_INST_RETIRED.SCALAR_SINGLE (Event=0xc7, Umask=0x02) など
scalar, SSE, AVX命令それぞれ実行した回数がとれます
UOPS_ISSUED.SINGLE_MUL (Event=0x0e, Umask=0x40)
MULの回数がとれます

VTune なら、そのまま名前を指定してカウントが取れると思います(使ったことないのでよくわからないです)

perf なら、

$ perf stat -e r01b1 ./a.out # 01b1 = Event=0xb1, Umask=0x01

のようにすればとれます

と、いうような話をすると、「別にポートごとに取れてもあんまりよくわからないんだが…」みたいな、至極もっともな意見をいただきました。確かに、そのとおりだと思います。

pin で命令数をカウントする

追記

pin を使った emulator の sde の標準機能で同様のことができるとの情報をもらいました。

https://twitter.com/xmmymmzmm/status/658914067323613185

$ sde -omix mix.txt — ./a.out

のようにすると、命令や基本ブロック、関数毎の実行回数がmix.txtに出力されます。

というわけで、何の役にも立たないと言われたので少し考えたのですが、pin を使えばそれっぽい値が取れそうな気がしたのでやってみました。

pinは…ひとことで説明するのは難しいので、 公式サイト からリンクが貼られている https://software.intel.com/en-us/file/cgo2013pdf/download?token=TOO_aGtH などを見てもらったほうがよいのですが、x86 の命令や関数にフックを入れて、x86機械語に自分の処理を埋め込めるツールです。

pin には xed というx86機械語を解析するライブラリも含まれているので、これを使うと、実行中のプログラムの機械語の挙動を調べるといったことも可能になります。Intel社のメモリデバッガであるInspectorもこのpinを使って実装されています。

これを使えば実行された全命令をカウントすることも可能ですね。ちょうどサンプルに全命令数をカウントするというサンプルがあったので(source/tools/ManualExamples/inscount0.cpp)、それを改造して命令を種類ごとにカウントするtoolを作ってみました。

https://bitbucket.org/fixstars/blog/src/master/pin/inscount0.cpp?fileviewer=file-view-default

ビルドは面倒なので、pinのサンプルを書き換えて、サンプルのmakefileをそのまま使うのがよいと思います。

  1. pin をダウンロード
  2. source/tools/ManualExamples/inscount0.cpp を上のファイルに置き換え
  3. source/tools をビルド
  4. できた source/tools/ManualExamples/inscount0.so を手元にコピー
  5. pin.sh -t inscount0 — ./a.out で実行

で a.out の命令カウントができます

#include <stdio.h>

int main()
{
    int i;
    for (i=0; i<100000000; i++) {
        asm volatile ("paddd %%xmm0, %%xmm0":::"memory");
    }
    return 0;
}

を実行すると、inscount.outに

..(略)..
NOP : 275
NOT : 6
OR : 237
PADDD : 100000000
PCMPEQB : 14
PMOVMSKB : 8
..(略)..

などと出力されて、paddd が 100000000回実行されていることが確認できます

Tags

About Author

nakamura

Leave a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Recent Comments

Social Media