相同功能消耗的时钟数根据其执行顺序而急剧变化

时间:2018-09-16 13:59:43

标签: c linux

我试图测量c中顺序搜索所消耗的时钟周期。

int seqsearch(int arr[], int n, int val){
    for(int i = 0; i < n ; i++){
        if(arr[i] == val)
            return i;
    }
    return -1;
}

void main(){
    int arr[20000];
    for(int i = 0; i < 20000; i++){
        arr[i] = i;
    }
    int search = 17777;
    double time;
    clock_t start, end, consumed;
    start = clock();
    printf("\nSearch for %d :%d\n", search, seqsearch(arr, 20000, search));
    end = clock();
    consumed = end - start;
    printf("\nNo. of clocks consumed = %ld\n", consumed);
    time = (end - start) / CLOCKS_PER_SEC;
    printf("\nRuntime = %lf\n", time);
    start= clock();
    printf("\nSearch for %d :%d\n", search, seqsearch(arr, 20000, search));
    end = clock();
    consumed = end - start;
    printf("\nNo.of clocks consumed:%ld\n", consumed);
    time = (end - start) / CLOCKS_PER_SEC;
    printf("\nRuntime:%lf\n", time);
}

输出:

$ ./a.out

Search for 17777 :17777

No. of clocks consumed = 339

Runtime = 0.000000

Search for 17777 :17777

No.of clocks consumed:177

Runtime:0.000000

我每次执行它时,第二次执行所消耗的时钟周期都比第一次执行时所消耗的时钟周期少得多。如果我几乎在同一时间执行两次相同的功能,那么两次执行都不应占用几乎相同的时钟周期。

3 个答案:

答案 0 :(得分:2)

我能够重现您的原始结果(稍作调整即可正确打印时间):https://ideone.com/ilQcmU

然后,我制作了一个版本,该版本没有将对printf的调用计时,因为它很慢并且与您要计时的事物无关:https://ideone.com/gVC01c

...
int result;
start = clock();
result = seqsearch(arr,20000,search);
end = clock();
printf("\nSearch for %d :%d\n",search, result);
consumed = end - start;
printf("No. of clocks consumed = %ld\n",consumed);
time = (double)consumed/CLOCKS_PER_SEC;
printf("Runtime = %lf\n",time);
...

以相同方式修改了第二个打印输出。结果表明,这很可能是您的罪魁祸首:

Search for 17777 :17777
No. of clocks consumed = 10
Runtime = 0.000010

Search for 17777 :17777
No.of clocks consumed:9
Runtime:0.000009

然后,我将整个过程放入一个循环中,以检查缓存是否具有明显的效果:https://ideone.com/xYsL5x

...
int result, i;
for(i = 0; i < 10; i++) {
    start = clock();
    result = seqsearch(arr,20000,search);
    end = clock();
    printf("\nSearch for %d :%d\n",search, result);
    consumed = end - start;
    printf("No. of clocks consumed = %ld\n",consumed);
    time = (double)consumed/CLOCKS_PER_SEC;
    printf("Runtime = %lf\n",time);
}
...

看起来这里的缓存似乎不存在问题,但是有了这样的时序分辨率,很难确定。即使确实起作用,这显然也不重要。

为完整起见,我将打印输出放回循环https://ideone.com/HnYkVd中的计时中。

...
int i;
for(i = 0; i < 10; i++) {
    start = clock();
    printf("\nSearch for %d :%d\n",search, seqsearch(arr,20000,search));
    end = clock();
...

在这里,有明显可见的启动效果。我认为它不一定要缓存。我认为打印机制比其他任何方式更有可能对缓冲区进行重新分配。

答案 1 :(得分:1)

您在这里观察到的是缓存的效果。初次调用该函数时,seqsearch访问的数据将被缓存。在seqsearch的第二次调用期间(大多数(如果不是全部)),数据在缓存中将已经可用。这样可以加快访问速度,从而减少时间。 您可以通过向此函数添加第三个调用来验证这一点,这将导致与第二个调用几乎相等的时间。

答案 2 :(得分:1)

您应该在调用printf之前确定经过的时间。您目前在计时中包括了printf及其副作用