我正在尝试找到一种方法来获取 C 中一段代码的执行时间。我已经从 time.h 尝试了 time() 和 clock(),但似乎 time() 返回秒和时钟() 似乎给了我毫秒(或厘秒?)不过我想要更精确的东西。有没有办法以至少微秒的精度抓住时间?
这只需要能够在 Linux 上编译。
你提到clock()
和time()
- 你在找gettimeofday()
吗?这将填充 a struct timeval
,其中包含秒和微秒。
当然,实际分辨率取决于硬件。
对于它的价值,这里只是几个宏:
#include <time.h>
clock_t startm, stopm;
#define START if ( (startm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define STOP if ( (stopm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define PRINTTIME printf( "%6.3f seconds used by the processor.", ((double)stopm-startm)/CLOCKS_PER_SEC);
然后只需使用它:
main() {
START;
// Do stuff you want to time
STOP;
PRINTTIME;
}
您需要一个分析器应用程序。
在 SO 和搜索引擎上搜索关键字:linux profiling
试试“bench.h”;它可以让你放一个 START_TIMER;和 STOP_TIMER("name"); 进入您的代码,允许您任意对代码的任何部分进行基准测试(注意:仅推荐用于较短的部分,而不是花费数十毫秒或更长时间的事情)。它精确到时钟周期,尽管在极少数情况下它可以改变中间代码的编译方式,在这种情况下,最好使用分析器(尽管分析器通常更努力地用于特定的代码部分)。
它仅适用于 x86。
您可能想在谷歌上搜索仪器工具。
您不会找到可以让您超越平台时钟分辨率的库调用。要么按照另一张海报的建议使用分析器(man gprof),要么 - 快速而肮脏 - 在有问题的代码部分周围放置一个循环以多次执行它,并使用时钟()。
gettimeofday()
为您提供微秒的分辨率,而clock_gettime()
为您提供纳秒的分辨率。
int clock_gettime(clockid_t clk_id, struct timespec *tp);
clk_id
标识要使用的时钟。CLOCK_REALTIME
如果您希望所有进程都可以看到系统范围的时钟,请使用此选项。用于CLOCK_PROCESS_CPUTIME_ID
每个进程的计时器和CLOCK_THREAD_CPUTIME_ID
特定于线程的计时器。
如果您在 x86 或 x64 上进行开发,为什么不使用时间戳计数器:RDTSC。
它将比诸如 time() 或 clock() 之类的 Ansi C 函数更可靠,因为 RDTSC 是一个原子函数。为此目的使用 C 函数可能会带来问题,因为您无法保证它们正在执行的线程不会被切换出去,因此它们返回的值将不是您尝试测量的实际执行时间的准确描述.
使用 RDTSC,您可以更好地衡量这一点。您需要将滴答计数转换回人类可读的时间 H:M:S 格式,这将取决于处理器时钟频率,但谷歌搜索,我相信您会找到示例。
但是,即使使用 RDTSC,您也将包括代码停止执行的时间,而如果您需要精确测量,则比使用 time()/clock() 更好的解决方案,您将不得不求助于分析器来检测您的代码并考虑到您的代码由于上下文切换或其他原因而没有实际执行的情况。
这取决于条件。分析器非常适合一般的全局视图,但是如果您真的需要准确的视图,我的建议是 KISS。只需在循环中运行代码,这样就需要一分钟左右才能完成。然后根据总运行时间和执行的迭代计算一个简单的平均值。
这种方法允许您:
使用低分辨率计时器获得准确的结果。
不会遇到仪器干扰靠近处理器的高速缓存(l2、l1、分支..等)的问题。然而,在紧密循环中运行相同的代码也可以提供可能无法反映现实世界条件的乐观结果。
不知道您正在使用哪个环境/操作系统,但如果另一个线程、任务或进程在中间抢占了您的定时代码,您的时间可能不准确。我建议探索诸如互斥锁或信号量之类的机制,以防止其他线程抢占您的进程。