命令単位の時間を計測する (準備)

2014年11月18日

命令単位の時間をはかってみましょう。この場合は、命令のクロック単位で知りたいことが多いので、CPU_CLK_UNHALTEDの値を使ってみます。
https://proc-cpuinfo.fixstars.com/2014/11/cpuclkunhalted.html
と、その前に、このCPU_CLK_UNHALTEDの値を取得する処理のオーバーヘッドも計測しておきましょう。read を使っているのでそれなりに大きな値になっている可能性があります。
https://bitbucket.org/fixstars/blog/src/76fcc97d7ab8df900b37592f852e52dbe34e1359/small_test/perf-read-overhead.c?at=master
動かしてみたところ、手元のマシンでは、平均 2000clk 程度のようです。計測対象が、200000clk(3.4GHz CPU で60usec)以上あるなら、オーバーヘッドは1%以下になるので無視して良いでしょう。
それでは以下のようにします
https://bitbucket.org/fixstars/blog/src/c25920cdac8cc69d4acd0ea2f1d493e147e398d1/small_test/inst-bench-template.c?at=master
GCC 拡張 asm を書いているので、あひーと思う人もいるかもしれませんが、今回は命令単位で計測したいので仕方ありません。
色々書いてますが、 ここ

#define INST                                            \
    "add %%eax, %%eax\n\t"

の箇所に書かれた命令を計測しています。今回の場合は、32bit加算を計測しています。
これを動かすと、

 $ ./a.out
add %%eax, %%eax

clk = 1.002997

などと出力されて、この命令が1clkで実行できることがわかります。

#define INST                                            \
    "add %%eax, %%eax\n"                              \
    "add %%eax, %%eax\n\t"
 $ ./a.out
add %%eax, %%eax
add %%eax, %%eax

clk = 2.010417

add をふたつ並べると、2clk になることがわかります。
さて、これで命令を計測する準備ができました…かのように見えますが、その前に、重要なことを確認しておきます。
二つ並んだ加算を次のように変更します

#define INST                                            \
    "add %%eax, %%eax\n"                              \
    "add %%ecx, %%ecx\n\t"

すると、実行結果は以下のように変化します。

 $ ./a.out
add %%eax, %%eax
add %%ecx, %%ecx

clk = 1.056262

eax の加算を二回実行した場合、処理時間は2clkでしたが、eax の加算と、ecx の加算を並べると、処理時間は1clkになりました。
現代のコンピュータは、さまざまな箇所が並列実行されるため、1個のデータに対して複数回処理を行う場合と、複数個のデータに対して、一回の処理を行う場合では、性能の特性が大きく変わります。
この現象は、命令単位での処理時間に限らず、メモリアクセス、マルチスレッド、HDD、プロジェクトの人員のアサイン(?)まであらゆるレイヤで見られる現象です。
次回、この違いについて、少し説明します。

Tags

About Author

nakamura

Leave a Comment

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

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

Recent Comments

Social Media