このブログは、株式会社フィックスターズのエンジニアが、あらゆるテーマについて自由に書いているブログです。
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ぐらい良くなりそうな気がしますね!(確実に無視できる誤差ですが)
コンピュータビジョンセミナーvol.2 開催のお知らせ - ニュース一覧 - 株式会社フィックスターズ in Realizing Self-Driving Cars with General-Purpose Processors 日本語版
[…] バージョンアップに伴い、オンラインセミナーを開催します。 本セミナーでは、...
【Docker】NVIDIA SDK Managerでエラー無く環境構築する【Jetson】 | マサキノート in NVIDIA SDK Manager on Dockerで快適なJetsonライフ
[…] 参考:https://proc-cpuinfo.fixstars.com/2019/06/nvidia-sdk-manager-on-docker/ […]...
Windowsカーネルドライバを自作してWinDbgで解析してみる① - かえるのほんだな in Windowsデバイスドライバの基本動作を確認する (1)
[…] 参考:Windowsデバイスドライバの基本動作を確認する (1) - Fixstars Tech Blog /proc/cpuinfo ...
2021年版G検定チートシート | エビワークス in ニューラルネットの共通フォーマット対決! NNEF vs ONNX
[…] ONNX(オニキス):Open Neural Network Exchange formatフレームワーク間のモデル変換ツー...
YOSHIFUJI Naoki in CUDAデバイスメモリもスマートポインタで管理したい
ありがとうございます。別に型にこだわる必要がないので、ユニバーサル参照を受けるよ...