如何测试不同算法的效率,例如排序算法?我用clock_gettime
尝试一下。这准确吗?有什么方法可以解决这个问题吗?
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
/* compute interval: end - start */
struct timespec diff(struct timespec start, struct timespec end);
/* tested algorithm, just an example. Print 10000 lines "hello" */
void testFunc(void);
int main(void)
{
struct timespec start;
struct timespec end;
struct timespec interval ;
clock_gettime(CLOCK_REALTIME, &start);
/* call the tested algorithm */
testFunc();
clock_gettime(CLOCK_REALTIME, &end);
interval = diff(start, end);
printf("%lld.%.9ld(seconds)\n", (long long)interval.tv_sec, interval.tv_nsec);
return 0;
}
/* compute interval: end - start */
struct timespec diff(struct timespec start, struct timespec end)
{
struct timespec temp;
if ((end.tv_nsec - start.tv_nsec) < 0) {
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
}
else {
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return temp;
}
/* tested algorithm, just an example. Print 10000 lines "hello" */
void testFunc(void)
{
int i;
for (i = 0; i < 10000; i++) {
printf("hello\n");
}
}
答案 0 :(得分:2)
您可以使用time
命令。可以找到一个很好的解释here。首先将源代码编译为可执行二进制文件。然后运行time ./executable_code
并且不要根据一两个测试做出决定。祝你好运!
答案 1 :(得分:1)
根据您对效率的意义,有很多方法可以测试。最简单的是Parnab使用time
命令的建议。但是,如果你真的想了解发生了什么,那可能还不够。
perf tool允许您访问更多指标,例如周期数,不同级别缓存的缓存命中/未命中数,错误预测分支数等等。还有一个API可以从C访问perf工具,但它没有很好地记录。存在其他工具,例如PAPI,但我不知道它们彼此之间的差异。
此外,由于排序算法(我猜)是数据相关的(这意味着它们不会执行相同数量的指令,具体取决于它们排序的数组),您需要在相同的输入上比较它们,它可能不是很很容易,因为有些人可能更好地排序几乎排序的数组。
答案 2 :(得分:1)
在测试算法时,除了所讨论的精确算法之外,通常最好除去所有多余的代码(例如,将算法本身与程序启动,文件读取,数据初始化隔离,除了算法的一部分)正在接受测试)。这是使用命令行中的time
无法做到的一个限制。
clock_gettime
函数很不错,因为它允许纳秒粒度。但是,clock ()
函数也可用于计时算法。 clock()
的一般用途是:
#include <time.h>
...
int main () {
double t1 = 0.0, t2 = 0.0;
srand (time (NULL));
...
t1 = clock (); /* get start time (as double) */
quicksort (a, 0, TESTLIM - 1); /* test whatever you need */
t2 = clock (); /* get end time (as double) */
printf ("\n quick1 (%lf sec)\n", (t2-t1)/CLOCKS_PER_SEC);
返回的时间差异是代码执行的粗略时间。它不是精确的挂起时间,因为CLOCKS_PER_SEC
被指定为常量值,无论它在哪台机器上运行。 (POSIX要求CLOCKS_PER_SEC
等于1000000
)
使用clock_gettime
或clock
都可以,但正如其他答案中所述,不要期望仅基于2次运行获得良好的近似值,并使用大量迭代。
clock_gettime
提供更多灵活性的地方在于允许选择使用的时钟,例如CLOCK_MONOTONIC_RAW
,CLOCK_PROCESS_CPUTIME_ID
等,根据您的需要,可能有助于保护计时器免受中断。 (有关各种时钟行为的完整讨论,请参阅man clock_gettime
)您可以使用与clock_gettime
类似的实现,例如
#include <stdio.h>
#include <time.h>
typedef struct timespec timespec;
timespec diff (timespec start, timespec end);
int main (void) {
timespec time1, time2, tmp;
int temp;
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &time1);
for (int i = 0; i < 242000000; i++)
temp += temp;
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &time2);
tmp = diff (time1, time2);
printf (" timediff %ld:%ld\n", tmp.tv_sec, tmp.tv_nsec);
return 0;
}
timespec diff (timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec - start.tv_nsec) < 0) {
temp.tv_sec = end.tv_sec - start.tv_sec - 1;
temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec - start.tv_sec;
temp.tv_nsec = end.tv_nsec - start.tv_nsec;
}
return temp;
}
(示例由profiling-code-using-clock_gettime提供,如果测试此示例则禁用优化)
仔细查看并选择最适合您需求的那个。