c - 使用系统单调时钟分析相对 C 代码执行时间

标签 c linux macos profiling clock

是否有一种简单但可靠的方法来衡量 C 程序中两种算法实现之间的相对性能差异。更具体地说,我想比较实现 A 与 B 的性能?我正在考虑这样的方案:

  • 在单元测试程序中:

    1. 开始计时
    2. 调用函数
    3. 停止计时器
    4. 获取开始停止时间之间的差异
  • 为一对函数 A 和 B 运行上面的方案,然后获得执行时间的百分比差异以确定哪个更快。

在做一些研究后,我遇到了关于使用 Monotonic clock on OSX 的问题在 C 中,这显然可以给我至少纳秒级的精度。明确地说,我知道精确的、受控的测量很难执行,就像在 "With O(N) known and system clock known, can we calculate the execution time of the code? 中讨论的那样。 ,我认为在这种情况下应该无关紧要,因为我只想要一个相对测量值。

综合考虑,对于我想要执行的那种分析,这是一种充分有效的方法吗?有没有我可能遗漏的细节或注意事项?

最佳答案

我对您概述的时序方案所做的主要修改是确保将相同的时序代码用于两个函数 - 假设它们确实具有相同的接口(interface),方法是将函数指针传递给骨架代码。

例如,我有一些代码可以对一些函数进行计时,这些函数可以验证给定数字是否为素数。控制函数为:

static void test_primality_tester(const char *tag, int seed, int (*prime)(unsigned), int count)
{
    srand(seed);
    Clock clk;
    int nprimes = 0;
    clk_init(&clk);

    clk_start(&clk);
    for (int i = 0; i < count; i++)
    {
        if (prime(rand()))
            nprimes++;
    }
    clk_stop(&clk);

    char buffer[32];
    printf("%9s: %d primes found (out of %d) in %s s\n", tag, nprimes,
           count, clk_elapsed_us(&clk, buffer, sizeof(buffer)));
}

我很清楚 srand() — why call it once? , 但使用点 srand()每次调用此函数一次是为了确保测试处理相同的随机数序列。在 macOS 上,RAND_MAX0x7FFFFFFF .

类型Clock包含两个类似物 struct timespec结构,用于开始和停止时间。 clk_init()函数初始化结构; clk_start()在结构中记录开始时间; clk_stop()在结构中记录停止时间;和 clk_elapsed_us()以微秒为单位计算开始时间和停止时间之间耗时。该包旨在为我提供跨平台的可移植性(代价是在确定编译时可用的最佳亚秒级计时例程时遇到一些麻烦)。

您可以在 Github 的存储库中找到我的定时器代码 https://github.com/jleffler/soq , 在 src/libsoq目录 — 文件 timer.htimer.c .该代码尚未 catch 具有 clock_gettime() 的 macOS Sierra , 虽然它可以编译为与 -DHAVE_CLOCK_GETTIME 一起使用作为命令行编译器选项。

这段代码是从一个函数中调用的 one_test() :

static void one_test(int seed)
{
    printf("Seed; %d\n", seed);
    enum { COUNT = 10000000 };
    test_primality_tester("IsPrime1", seed, IsPrime1, COUNT);
    test_primality_tester("IsPrime2", seed, IsPrime2, COUNT);
    test_primality_tester("IsPrime3", seed, IsPrime3, COUNT);
    test_primality_tester("isprime1", seed, isprime1, COUNT);
    test_primality_tester("isprime2", seed, isprime2, COUNT);
    test_primality_tester("isprime3", seed, isprime3, COUNT);
}

并且主程序可以取一个或一系列种子,或者使用当前时间作为种子:

int main(int argc, char **argv)
{
    if (argc > 1)
    {
        for (int i = 1; i < argc; i++)
            one_test(atoi(argv[i]));
    }
    else
        one_test(time(0));
    return(0);
}

关于c - 使用系统单调时钟分析相对 C 代码执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41154227/

相关文章:

c - 用 C 程序求阶乘

c++ - 逻辑/关系表达式优化

c - 在子进程中读取

linux - 如何将 'stdout' 重定向到 'stderr' 并将 'stderr' 重定向到 'stdout'?

c# - 我在哪里可以下载 MonoMac 的编译版本?

c - 寻找用 C 实现的快速排序整数数组交集/union 算法

linux - 破译bash文件中的不同列

linux - ALSA 为 Skype 组合麦克风输入和扬声器输出

ruby - 在 RVM 中安装 Ruby 1.9.3 时出错 - Make error

macos - 从图表中提取音频数据 kAudioUnitSubType_GenericOutput