看到《程序设计实践》一书上第7章讲“测试”,里面有一小节描述了作者测试在自己机器上一些操作的耗时。
如整数的加减乘除,浮点数的加减乘除。觉得很有意思,就按照书上的想法,自己写了一个测试集。写的并不好,不过应该没多大问题。
首先要解决的问题是计时,我找到了三个方法:
(1)用C标准库里的clock()函数,问题是精度不够。顶多是毫秒。
(2) 用linux系统的库函数gettimeofday(),可以精确到微秒。似乎还有一个clock_gettime()函数也很不错。
(3) 用CPU指令,说是CPU里有一个计数器,可以用RDTSC指令来取出当前计数,这样分别取出两个计数,然后除以机器的主频,就能得到时间了,精确到纳秒级。
第一种精度太低,第三种太麻烦,关于第三种在网上有很多资料。我选第二种。
基本的计时代码结构是:
- #include <sys/time.h>
-
...
-
-
struct timeval start, end;
-
double ns;
-
-
gettimeofday(&start, NULL);
-
/* code */
- for(i = 0; i < N; i++)
- ival++;
-
gettimeofday(&end, NULL);
-
ns = 1e3*(1e6*(end.tv_sec-start.tv_sec)+end.tv_usec-start.tv_usec);
- true_time = ns / N;
这里我还是将时间转成了纳秒刻度。
计时中间的代码就是一个循环, 因此最终时间还要除一个循环次数。
下面是我测试的结果,
我的电脑双核处理器:Pentium(R)Dual-Core CPU T4300@2.10GHz, ubuntu10.10系统。
gcc 4.4.5编译器,编译时候没开启优化选项。
后面的数字是时间,单位是纳秒
null loop: 3.360577 # 空循环
# 整数的操作
ival++: 3.352575
++ival: 3.352027
ival1+ival2: 3.864244
ival1-ival2: 3.258683
ival1*ival2: 3.679492
ival1/ival2: 4.871335
ival1%ival2: 4.876412
# 单精度浮点操作
fval1+fval2: 3.734369
fval1-fval2: 3.713846
fval1*fval2: 3.638461 # 可见浮点乘耗时并不多,不过除就很多了。
fval1/fval2: 10.947827
# 双精度浮点操作
dval1+dval2: 3.161844
dval1-dval2: 2.819050
dval1*dval2: 2.514910 # 双精度并不一定比单精度计算的慢
dval1/dval2: 10.611016
# 数组操作
a[i]=i: 4.019270
a[a[i]]=i: 5.042540
a[a[a[i]]]=i: 7.507980
# 分支
if(i==5): 3.749296
if(i!=5): 4.310709
# 函数调用
func(): 3.363777
func(a): 3.414053
func(a, b): 3.964201
func(a, b, c): 4.341260 # 多一些参数,应该就多了一些压栈操作
# string库里的三个函数
strcpy(d, "0123456789"): 17.458487
memcpy(d, "0123456789"): 10.090370 # 还是memcpy要快一些
strcmp(s, s): 3.424462
在我的测试中,我觉得最不可思意的是下面的代码:
- #include <stdio.h>
-
#include <time.h>
-
-
#define N 0x7FFFFFFFU
-
int main()
-
{
-
unsigned int i;
-
double a,b,c;
-
unsigned long long t;
-
clock_t c_start, c_end;
-
printf("%d\n", sizeof(clock_t));
-
-
a = 2.3928318;
-
b = 83.328321;
-
-
c_start = clock();
-
for(i = 0; i < N; i++)
-
; /* null loop */
-
c_end = clock();
-
t = c_end - c_start;
-
printf("%llu\n", t);
-
-
c_start = clock();
-
for(i = 0; i < N; i++)
-
c = a * b; /* float multi */
-
c_end = clock();
-
t = c_end - c_start;
-
printf("%llu\n", t);
-
-
return 0;
-
}
运行后,我这测得的时间是:
数字4是clock_t占的字节数。
可见双精度浮点运算的时间要比空的循环还要少。 不得其解!
我在winXP下测试时,浮点运算要比空循环时间多那么一小点。
阅读(5289) | 评论(0) | 转发(0) |