函数执行时间测量异常:prefixAverages2耗时显示为0的问题排查
嗨,我来帮你搞定这个计时的小麻烦!首先告诉你结论:不需要关闭什么“时钟流”,clock()本身不是流操作,你的用法没问题。问题出在prefixAverages2的效率实在太高了,单次运行时间短到超过了clock()的测量精度,所以差值计算出来是0。
为什么会这样?
clock()函数返回的是程序从启动到当前时刻使用的CPU时钟周期数,而CLOCKS_PER_SEC定义了每秒对应的时钟周期数(大多数系统里是1000或者1000000)。如果你的程序运行时间小于1/CLOCKS_PER_SEC秒(比如1毫秒或者1微秒),那么end - begin的结果就会是0,最终计算出的耗时自然是0.000毫秒。
prefixAverages2是O(n)的时间复杂度,而prefixAverages1是O(n²),当输入量小于10万时,O(n)的操作几乎瞬间完成,clock()根本抓不到它的耗时。
怎么解决?
这里有两个实用的方法:
方法1:重复运行多次取平均
把prefixAverages2的调用放在一个循环里,重复运行几百甚至几千次,然后把总耗时除以运行次数,得到单次的平均耗时。这样总时间足够长,就能被clock()准确测量了。
修改后的case2代码示例:
case 2: printf("Beginning prefixAverages2\n"); const int iterations = 1000; // 重复1000次 clock_t begin2 = clock(); for (int k = 0; k < iterations; k++) { int *a2 = prefixAverages2(input); free(a2); } clock_t end2 = clock(); double total_time = (double)(end2 - begin2) * 1000.0 / CLOCKS_PER_SEC; double time_spent2 = total_time / iterations; printf("Algorithm took %f milliseconds to execute (average over %d runs)\n", time_spent2, iterations); break;
方法2:使用更高精度的计时函数
如果你的系统支持,可以用精度更高的计时API,比如:
- Linux/macOS下用
gettimeofday()或者clock_gettime() - Windows下用
QueryPerformanceCounter() - C11标准的
timespec_get()(跨平台)
举个用clock_gettime()的例子(Linux/macOS):
#include <time.h> // 在case2里替换clock()的部分 struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); int *a2 = prefixAverages2(input); clock_gettime(CLOCK_MONOTONIC, &end); free(a2); double time_spent2 = (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_nsec - start.tv_nsec) / 1000000.0; printf("Algorithm took %f milliseconds to execute\n", time_spent2);
额外小提醒
顺便注意下你的两个prefixAverages函数有个小差异:prefixAverages1里i=0的时候,sum是0,a[0]是0;而prefixAverages2里i=0的时候sum是rand()的值,a[0]是那个随机数。如果这不是你故意的,可能需要调整下逻辑哦~
内容的提问来源于stack exchange,提问作者InfoSecNick

