【发布时间】:2013-07-31 12:19:52
【问题描述】:
我编写了一些代码来测量每个字节的 cpu 周期。我越来越消极cpb 但不知道为什么...它告诉我cpb = -0.855553 cycles/byte
我的伪代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
uint64_t rdtsc(){
unsigned int lo,hi;
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
return ((uint64_t)hi << 32) | lo;
}
int main()
{
long double inputsSize = 1024;
long double counter = 1;
long double cpuCycleStart = rdtsc();
while(counter < 3s)
function(args);
long double cpuCycleEnd = rdtsc();
long double cpb = ((cpuCycleEnd - cpuCycleStart) / (counter * inputsSize));
printf("%Lf cycles/byte\n", cpb);
return 0;
}
编辑,改进代码,结果相同(否定):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned long rdtsc( void )
{
unsigned long lo, hi;
asm( "rdtsc" : "=a" (lo), "=d" (hi) );
return( lo );
}
int main()
{
long double counter;
long double inputsSize = 1024;
char *buff = createInput(inputsSize);
long double cpuCycleStart = rdtsc();
countDownTime(3.0);
for(counter=1; !secondsElapsed; counter++)
function(args);
long cpuCycleEnd = rdtsc();
long double cpb = ((cpuCycleEnd - cpuCycleStart) / (counter * inputsSize));
printf("%Lf cycles/byte\n", cpb);
return 0;
}
真的很奇怪。编写测试代码:
printf("\n%lu cpuCycleEnd \n%lu cpuCycleStart \n", cpuCycleEnd, cpuCycleStart);
printf("\n%lu counter\n%lu inputsSize \n\n", counter, inputsSize);
long double cpb = (((long double)cpuCycleEnd - (long double)cpuCycleStart) / ((long double)counter * (long double)inputsSize));
printf("%Lf cycles/byte\n", cpb);
其中显示:
30534991 cpuCycleEnd
1139165971 cpuCycleStart
1273029 counter
1024 inputsSize
-0.850450 cycles/byte
有什么想法吗?
【问题讨论】:
-
为什么要将
uint64_t存储到long double中? -
顺便说一下,在现代处理器上,
rdtsc被定义为测量实时(挂钟时间),而不是处理器时间。英特尔几年前更改了规范。在处理器速度发生变化或各种电源状态时,它不会测量处理器周期。 -
在现有的
printf之前,分别打印cpuCycleEnd、cpuCycleStart、counter和inputsSize的值。如果counter或inputsSize是否定的,找出原因并修复它们。如果cpuCycleEnd小于cpuCycleStart,找出原因。柜台包装了吗?它们是否接近rdtsc调用返回的其他值(如果您插入更多调用来查看)?unsigned long是您的 C 实现中的 64 位吗?如果将rdtsc的值打印为unsigned long,是否与将其转换为double后打印的值相同? -
请注意,64 位
double无法存储 64 位unsigned long的所有位。如果rdtsc值设置了一些高九位,您可能会遇到舍入错误。这应该会导致减法中的精度丢失,但不会丢失负值(舍入的效果应该是单调的),直到计数器换行。在任何情况下,最好将rdtsc值存储为uint64_t,直到它们被减去,然后如果需要,将减去的结果转换为double。 -
当我为 i386 编译和执行(
unsigned long是 32 位)时,我得到一个否定的结果(通常),但当我为 x86_64 编译和执行(unsigned long是 64 位)时却没有。检查您的构建目标是否为 64 位目标。添加一个语句printf("sizeof(unsigned long) is %zu bytes.\n", sizeof(unsigned long));,看看它是否打印了8。最好使用#include <stdint.h>并使用uint64_t而不是unsigned long。此外,我必须进行一些修改才能编译。如果问题仍然存在,请发帖self-contained compilable example。
标签: c performance benchmarking cpu-usage