我想要对C/C++代码进行基准测试。我想要测量CPU时间,墙上时间和每字节的周期数。我编写了一些测量函数,但是在计算每字节的周期数时出现了问题。
为了获得CPU时间,我编写了一个带有RUSAGE_SELF的getrusage()函数,为了获得墙上时间,我使用了带有MONOTONIC的clock_gettime函数,为了获取每字节的周期数,我使用rdtsc函数。
我处理一个大小为1024的输入缓冲区:char buffer [1024]。如何进行基准测试:
1. 进行热身阶段,只需简单地调用fun2measure(args)1000次: ``` for(int i=0; i<1000; i++) fun2measure(args); ```
2. 然后,进行实时基准测试,以获取墙上时间: ``` unsigned long i; double timeTaken; double timeTotal = 3.0; // 处理3秒钟 for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args); ``` 3. 对于CPU时间(基本相同): ``` for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args); ``` 但是当我想要获得函数的CPU周期计数时,我会使用以下代码:
我的问题:
1. 这些结果可以吗? 2. 为什么当我增加时间时,cpu 总是显示每字节 0 次循环? 3. 我如何测量平均时间、平均值、标准差等统计数据? 4. 我的基准测试方法是否百分百正确?
干杯!
第一次编辑:
将更改为之后:
我的结果似乎还不错。所以问题#2不再是问题:)
为了获得CPU时间,我编写了一个带有RUSAGE_SELF的getrusage()函数,为了获得墙上时间,我使用了带有MONOTONIC的clock_gettime函数,为了获取每字节的周期数,我使用rdtsc函数。
我处理一个大小为1024的输入缓冲区:char buffer [1024]。如何进行基准测试:
1. 进行热身阶段,只需简单地调用fun2measure(args)1000次: ``` for(int i=0; i<1000; i++) fun2measure(args); ```
2. 然后,进行实时基准测试,以获取墙上时间: ``` unsigned long i; double timeTaken; double timeTotal = 3.0; // 处理3秒钟 for (timeTaken=(double)0, i=0; timeTaken <= timeTotal; timeTaken = walltime(1), i++) fun2measure(args); ``` 3. 对于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
的长度。但是当我将totalTime
增加到10秒时,我得到了奇怪的结果:
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. 我的基准测试方法是否百分百正确?
干杯!
第一次编辑:
将更改为之后:
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不再是问题:)
rdtsc
指令。我遇到过两个主要问题(也许还有其他问题):1)在许多多CPU系统上,TSC计数器不会保持同步,因此在开始和结束点之间迁移到不同的CPU将导致虚假结果;2)TSC可能可靠(或多或少)地计算周期,但是中断、重新调度等意味着这些周期可能并没有全部用于您的代码...尽管如此,只要您知道可能存在的问题,它仍然可以作为一个基本估计值。 - twalbergrdtsc
吗?还是在其之前使用cpuid
指令? - nullpointer