在 C 中测量处理器滴答声

Measuring processor ticks in C

我想计算在函数内执行相同代码时执行时间的差异。然而,令我惊讶的是,当我使用 clock()/clock_t 作为启动和停止计时器时,有时时钟差为 0。这是否意味着 clock()/clock_t 实际上 return 点击次数 处理器花在任务上?

经过一些搜索,在我看来 clock_gettime() 会 return 更细粒度的结果。确实如此,但我最终得到了任意数量的纳秒(?)秒。它暗示了执行时间的差异,但很难准确说明它究竟有多少点击差异。我需要做什么才能找到它?

#include <math.h>
#include <stdio.h>
#include <time.h>

#define M_PI_DOUBLE (M_PI * 2)

void rotatetest(const float *x, const float *c, float *result) {
    float rotationfraction = *x / *c;
    *result = M_PI_DOUBLE * rotationfraction;
}

int main() {

    int i;
    long test_total = 0;
    int test_count = 1000000;
    struct timespec test_time_begin;
    struct timespec test_time_end;

    float r = 50.f;
    float c = 2 * M_PI * r;
    float x = 3.f;
    float result_inline = 0.f;
    float result_function = 0.f;

    for (i = 0; i < test_count; i++) {
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &test_time_begin);
        float rotationfraction = x / c;
        result_inline = M_PI_DOUBLE * rotationfraction;
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &test_time_end);
        test_total += test_time_end.tv_nsec - test_time_begin.tv_nsec;
    }

    printf("Inline clocks %li, avg %f (result is %f)\n", test_total, test_total / (float)test_count,result_inline);

    for (i = 0; i < test_count; i++) {
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &test_time_begin);
        rotatetest(&x, &c, &result_function);
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &test_time_end);
        test_total += test_time_end.tv_nsec - test_time_begin.tv_nsec;
    }

    printf("Function clocks %li, avg %f (result is %f)\n", test_total, test_total / (float)test_count, result_inline);

    return 0;
}

我在 Linux 3.13.0-37-generic (Linux 薄荷 16)

谷歌搜索了一下后,我发现 clock() 函数可以用作查找执行的大部头的标准机制,但请注意,时间会根据负载的不同而有所不同你的处理器, 您可以使用下面的代码进行计算

clock_t begin, end;
double time_spent;

begin = clock();
/* here, do your time-consuming job */
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;

首先:正如评论中已经提到的,一个一个地执行一个 运行 时钟可能对你没有好处。如果一切都走下坡路,获取时间的调用实际上可能比实际执行操作花费的时间更长。

请计算多个 运行 秒的操作(包括预热阶段,以便所有内容都被交换)并计算平均 运行ning 次。

clock() 不保证是单调的。它也不是 处理器点击次数 (无论您将其定义为什么)程序具有 运行。描述 clock() 结果的最佳方式可能是“ 对任何一个 CPU 花费在当前进程计算上的时间的最大努力估计 ”。因此,出于基准测试目的,clock() 几乎没有用。

作为per specification:

The clock() function returns the implementation's best approximation to the processor time used by the process since the beginning of an implementation-dependent time related only to the process invocation.

另外

To determine the time in seconds, the value returned by clock() should be divided by the value of the macro CLOCKS_PER_SEC.

所以,如果你调用 clock() 的次数比解析的次数多,那你就不走运了。

对于 profiling/benchmarking,您应该——如果可能的话——使用现代硬件上可用的一种性能时钟。主要候选人可能是

编辑:问题现在引用 CLOCK_PROCESS_CPUTIME_ID,这是公开 TSC 的 Linux 方式。

是否有任何(或两者)可用取决于硬件也是操作系统特定的。