3

我想对 C/C++ 代码进行基准测试。我想测量 CPU 时间、挂墙时间和周期/字节。我写了一些测量函数,但是周期/字节有问题。

为了获得 cpu 时间,我编写了一个函数getrusage(),对于我使用的RUSAGE_SELF壁时间,以获得我使用的周期/字节。clock_gettimeMONOTONICrdtsc

我处理大小为 1024: 的输入缓冲区char buffer[1024]。我如何进行基准测试:

  1. 做一个热身阶段,简单地调用fun2measure(args)1000 次:

for(int i=0; i<1000; i++) fun2measure(args);

  1. 然后,针对挂钟时间做一个实时基准测试:

    `无符号长我; 双倍时间;双倍时间总计 = 3.0;// 处理 3 秒

    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args); `

  2. 对于 cpu 时间(几乎相同):

    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args);

但是当我想获得函数的 cpu 循环计数时,我使用这段代码:

`unsigned long s = cyclecount();
    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++)
    {
        fun2measure(args);
    }
    unsigned long e = cyclecount();

unsigned long s = cyclecount();
    for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = cputime(1), i++)
    {
        fun2measure(args);
    }
    unsigned long e = cyclecount();`

然后,计数周期/字节:((e - s) / (i * inputsSize);。这里inputsSize是 1024,因为它是buffer. 但是当我升到totalTime10 岁时,我得到了奇怪的结果:

10 秒:

Did fun2measure 1148531 times in 10.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 1000221 times in 10.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]

5秒:

Did fun2measure 578476 times in 5.00 seconds for 1024 bytes, 0 cycles/byte [CPU]
Did fun2measure 499542 times in 5.00 seconds for 1024 bytes, 7.000000 cycles/byte [WALL]

4s:

Did fun2measure 456828 times in 4.00 seconds for 1024 bytes, 4 cycles/byte [CPU]
Did fun2measure 396612 times in 4.00 seconds for 1024 bytes, 3.000000 cycles/byte [WALL]

我的问题:

  1. 这些结果好吗?
  2. 为什么当我增加时间时,我总是在 cpu 中得到 0 个周期/字节?
  3. 我如何测量此类基准测试的平均时间、平均值、标准偏差等统计数据?
  4. 我的基准测试方法 100% 可以吗?

干杯!

第一次编辑:

更改i为后double

Did fun2measure 1138164.00 times in 10.00 seconds for 1024 bytes, 0.410739 cycles/byte [CPU]
Did fun2measure 999849.00 times in 10.00 seconds for 1024 bytes, 3.382036 cycles/byte [WALL]

我的结果似乎还可以。所以问题#2不再是问题了:)

4

1 回答 1

1

您的 cyclecount 基准有缺陷,因为它包括 walltime/cputime 函数调用的成本。但总的来说,我强烈建议您使用适当的分析器,而不是尝试重新发明轮子。特别是性能计数器会为您提供可以依赖的数字。另请注意,周期非常不可靠,因为 CPU 通常不会以固定频率运行,或者内核可能会执行任务切换并暂停您的应用程序一段时间。

我个人编写基准测试,以便它们运行给定函数 N 次,因为 N 足够大,以便您获得足够的样本。然后我在外部应用诸如 linux perf 之类的分析器来让我得到一些难以推理的数字。在给定时间重复基准测试,然后您可以计算 stddev/avg 值,您可以在运行基准测试几次并评估分析器输出的脚本中执行此操作。

于 2013-08-08T17:55:08.570 回答