このブログは、株式会社フィックスターズのエンジニアが、あらゆるテーマについて自由に書いているブログです。
rdtscp や CPU_CLK_UNHALTED は、細かい性能を計測する場合には便利ですが、大きな粒度で計測したい場合、単位の変換などが面倒です。状況に応じて、色々な方法を使い分けると良いでしょう。
以下、思い付く範囲で時間計測方法について列挙していきます。これで全てでは無いと思いますが、知っていると役に立つこともあるかもしれません。(基本的にはLinuxで説明しています。Linux以外で使えるかどうかは調査していません)
コマンドの時間を計測できます。bash などで使える time コマンドは、シェルの組み込みコマンドですが、これとは別に/usr/bin/time というコマンドもあります。
/usr/bin/time コマンドに -v を付けると、もう少し色々と情報が取得できます
$ /usr/bin/time -v sleep 1
Command being timed: "sleep 1"
User time (seconds): 0.00
System time (seconds): 0.00
Percent of CPU this job got: 0%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.00
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 660
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 216
Voluntary context switches: 2
Involuntary context switches: 1
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0
スワップ回数、スレッド数、メモリ使用量最大量などを簡単に知るのに便利です
前回説明した、perf_event インターフェースのフロントエンドです。使いかたは色々ありますが、とりあえず、perf stat を使えば、time -v と同じような感覚でコマンドの時間を計測できます
$ perf stat cat /dev/null
Performance counter stats for 'cat /dev/null':
0.395229 task-clock (msec) # 0.026 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
176 page-faults # 0.445 M/sec
1,332,497 cycles # 3.371 GHz
932,228 stalled-cycles-frontend # 69.96% frontend cycles idle
<not supported> stalled-cycles-backend
829,973 instructions # 0.62 insns per cycle
# 1.12 stalled cycles per insn
158,572 branches # 401.215 M/sec
7,279 branch-misses # 4.59% of all branches
0.014989336 seconds time elapsed
/usr/bin/time -v とは違って、実行した命令数、分岐の回数、分岐ミス率などが取得できます。
POSIX には、絶対時間を取得するgettimeofdayという関数がありますが、これはobsoleteとなっています。
計測に使う場合にも、以下のような問題が発生する可能性があります。
かわりに、clock_gettime を使うことが推奨されています。clock_gettimeにCLOCK_MONOTONIC_RAWを渡すと、some unspecified starting point(?) からの時刻を取得できます。
Windows で同じように、時刻を計測するときは、QueryPerformanceCounter を使うと良いでしょう。
QueryPerformanceCounter は、なんらかの64bit カウンタ値を読めるWin32 APIです。このカウンタの増加周波数は、QueryPerformanceFrequency で取得できます。
#include <windows.h>
#include <stdio.h>
LARGE_INTEGER start, end;
int
main()
{
QueryPerformanceCounter(&start);
Sleep(1000);
QueryPerformanceCounter(&end);
double delta = end.QuadPart - start.QuadPart;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
printf("%f\n", delta/ freq.QuadPart);
}
POSIXインターフェースでは、内部でカウンタ→秒へ変換されてしまうのに対し、Win32インターフェースでは、表示の直前までハードウェアカウンタ値を保持できるので、ハードウェアが同じなら取得できる値が0.5bitぐらい良くなりそうな気がしますね!(確実に無視できる誤差ですが)
keisuke.kimura in Livox Mid-360をROS1/ROS2で動かしてみた
Sorry for the delay in replying. I have done SLAM (FAST_LIO) with Livox MID360, but for various reasons I have not be...
Miya in ウエハースケールエンジン向けSimulated Annealingを複数タイルによる並列化で実装しました
作成されたプロファイラがとても良さそうです :) ぜひ詳細を書いていただきたいです!...
Deivaprakash in Livox Mid-360をROS1/ROS2で動かしてみた
Hey guys myself deiva from India currently i am working in this Livox MID360 and eager to knwo whether you have done the...
岩崎システム設計 岩崎 満 in Alveo U50で10G Ethernetを試してみる
仕事の都合で、検索を行い、御社サイトにたどりつきました。 内容は大変参考になりま...
Prabuddhi Wariyapperuma in Livox Mid-360をROS1/ROS2で動かしてみた
This issue was sorted....