クロックで速度を計ろう の焼き直しですが、これから書くのは PPU で時間計測する方法です。SPU で処理を行っても普通はメインの PPU で時間を計る事になるため、とりあえず SPU 内での計測方法は書きません。
SPU で計測したい場合は Young risk taker さんの [Cell] SPE上での実行時間計測 を参照して下さい。
まず、linux で精度良く時間計測を行うには getrusage() を使います。
次の例では長時間の計測に耐えるようにしていますが、秒以下の計測では t.ru_utime.tv_usec だけで構いません。
#include <sys/resource.h>
unsigned long long microseconds()
{
rusage t;
timeval tv;
getrusage( RUSAGE_SELF, &t );
tv = t.ru_utime;
return ((unsigned long long)tv.tv_sec)*1000000 + tv.tv_usec;
}
更に精度が欲しい場合は、クロック数を取得します。
PowerPC (PPU) でクロック数を取得するには、アセンブラで mftb, mftbu を使用します。4 ギガクロック以下の計測では mftb だけで構いません。
inline unsigned long long raw_clk()
{
unsigned long long clkL, clkH;
asm volatile (
"mftb %0\n\t"
"mftbu %1\n\t"
: "=r"(clkL), "=r"(clkH) : : );
return (((unsigned long long)clkH) << 32) | clkL;
}
これら mftb, mftbu のクロック周波数は環境ごとに変える事ができ、CPU のクロック周波数と一致しているとは限りません。
PLAYSTATION3 に Fedora Core 5 を入れた状態では mftb のクロック周波数対 CPU のクロック周波数が 1:40 になっているようなので、CPU のクロック周波数に換算したい場合は 40 倍します。SPU のデクリメンタを使用する場合も同様に 40 倍して下さい。
inline unsigned long long cpu_clk()
{
return raw_clk() * 40;
}
ここで示したこれらの方法は、「現在の時間」を示すものであり、処理にかかった時間を計測する場合は、処理前と処理後の時間の差分を取って下さい。
microseconds() は 1,000,000 分の一秒、cpu_clk() は PLAYSTATION3 の場合 3,200,000,000 分の一秒単位で時間が得られます。