我正在编写一个程序来确定每秒可以运行多少NOP,但我得到的数字似乎非常小。
int main()
{
struct timeval tvStart, tvDiff, tvEnd;
unsigned int i;
unsigned long numberOfRuns = 0xffffffff;
gettimeofday(&tvStart, NULL);
for(i = 0; i < (unsigned int) 0xffffffff; i++)
{
hundred(); /*Simple assembly loop that runs 100 times and returns */
}
gettimeofday(&tvEnd, NULL);
timeval_subtract(&tvDiff, &tvEnd, &tvStart);
/* Get difference in time in microseconds */
unsigned long nopTime = (tvDiff.tv_sec * 1000000L) + tvDiff.tv_usec;
printf("NOP Seconds: %lu\n", nopTime);
gettimeofday(&tvStart, NULL);
for(i = 0; i < (unsigned int) 0xffffffff; i++)
{
none(); /* Assembly function that just returns */
}
gettimeofday(&tvEnd, NULL);
timeval_subtract(&tvDiff, &tvEnd, &tvStart);
/* Get difference in time in microseconds */
unsigned long retTime = (tvDiff.tv_sec * 1000000L) + tvDiff.tv_usec;
printf("RET Seconds: %lu\n", retTime);
unsigned long avgTime = nopTime - retTime;
/* Takes number of NOP runs and divides it by the time taken
and multiplies by 1,000,000 to convert to seconds */
printf("%lu\n", ((numberOfRuns * 100) / avgTime) * 1000000);
}
我要做的第一件事是运行一个由100个NOP指令0xffffffff
时间组成的汇编循环,并存储它在nopTime
中所用的时间。然后,我也这样做,而是调用刚刚返回的汇编函数。
我相信如果不是更多,我应该每秒至少获得1,000,000,000个NOP指令,但我甚至都不接近。这是我上次运行的输出:
NOP Seconds: 251077086
RET Seconds: 10450449
/* Calculated number of NOPs per second */
17000000
我不太习惯使用更大的数据类型,所以事情被截断了,我没有意识到这一点?我应该使用双打吗?似乎当我搞乱数据类型时,我会得到不同的数字,但它们也是相当小的数字。
我的逻辑错了吗?
答案 0 :(得分:1)
我不确定你是否可以在C中获得NOP,但可能使用内联汇编。但即使您可以使用内联汇编在for循环内编写NOP,实际循环也会生成算术和分支指令。
如果你在没有优化的情况下编译,你甚至会得到内存加载和存储,而且速度较慢。
除此之外,NOP的理论速度和流水线CPU上的NOP指令应该与CPU频率相同。
出于实际目的,如果你真的想要测量,你应该在只使用寄存器的汇编中编写一个循环,并且在循环内部你有NOP指令,就像它们适合单个指令缓存块或者几个块一样
如果你在C中执行此操作,请使用优化gcc -O3
进行编译,这样for循环计数器只是寄存器,并且还要确保NOP不会被优化掉。使用gcc -S
查看输出程序集。