请关注:::质疑BCB6的算术运算能力!

NowCan 2003-04-14 12:53:47
/*
test64.c
本程序用于测试unsigned __int64的性能。

根据测试结果,BCB6的命令行编译器BCC32 V5.6.4,
ilink32 V5.64对unsigned __int64的支持不好。
特别是对大于2^32的数进行求余和除法时性能很差!!

以下是我的测试结果。
(IBM笔记本PIII850/128M+WindowsXP Pro)
---------------------------------------------
测试加法(小于2^32)
用时:3655
测试加法(大于2^32)
用时:3595
测试开方(小于2^32)
10000
用时:21481
测试开方(大于2^32)
207484
用时:20760
测试求余(小于2^32)
94967337
用时:6449
测试求余(大于2^32)
94967339
用时:108286
测试除法(小于2^32)
42
用时:6239
测试除法(大于2^32)
42
用时:106473
*/

#include <math.h>
#include <windows.h>
#include <stdio.h>

/* */

int main(void)
{
unsigned __int64 a=0;
unsigned long i, j, k;
DWORD ts;

printf("测试加法(小于2^32)\n");
ts=GetTickCount();
for(i=0; i < 1000000000; ++i)
{
++a;
}

printf("用时:%lu\n", GetTickCount() - ts);

printf("测试加法(大于2^32)\n");
ts=GetTickCount();
a=4294967296;
for(i=0; i < 1000000000; ++i)
{
++a;
}

printf("用时:%lu\n", GetTickCount() - ts);

printf("测试开方(小于2^32)\n");
ts=GetTickCount();
a=0;
for(i=0; i < 100000000; ++i)
{
++a;
k=sqrt((double)a);
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

printf("测试开方(大于2^32)\n");
ts=GetTickCount();
a=42949672960;
for(i=0; i < 100000000; ++i)
{
++a;
k=sqrt((double)a);
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

printf("测试求余(小于2^32)\n");
ts=GetTickCount();
a=4294967295;
for(i=2; i < 100000000; ++i)
{
k=a % i;
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

printf("测试求余(大于2^32)\n");
ts=GetTickCount();
a=4294967297;
for(i=2; i < 100000000; ++i)
{
k=a % i;
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

printf("测试除法(小于2^32)\n");
ts=GetTickCount();
a=4294967295;
for(i=2; i < 100000000; ++i)
{
k=a / i;
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

printf("测试除法(大于2^32)\n");
ts=GetTickCount();
a=4294967297;
for(i=2; i < 100000000; ++i)
{
k=a / i;
}

printf("%lu\n", k);
printf("用时:%lu\n", GetTickCount() - ts);

return 0;
}
...全文
65 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
NowCan 2003-04-28
  • 打赏
  • 举报
回复
VC6的汇编和这个类似,只是不调用__llumod,而是_aullrem,又不知道是个什么东西。
这两个函数的实现有明显不同。
NowCan 2003-04-28
  • 打赏
  • 举报
回复
安装了VC6,看了一下,太复杂。
又做了一次对比,发现对于求余和除法,在小于2^32时,BCB6比VC6快大约1/3,但是大于2^32是,BCB6的速度明显慢下来。
我把BCB6的汇编写出来看看。
;
;
; printf("测试求余(大于2^32)\n");
;
?live1@608: ; ESI = k
push offset s@+184
call _printf
pop ecx
;
; ts=GetTickCount();
;
call GetTickCount
mov edi,eax
;
; a=4294967297;
;
?live1@640: ; ESI = k, EDI = ts
mov dword ptr [ebp-8],1
mov dword ptr [ebp-4],1
;
; for(i=2; i < 100000000; ++i)
;
mov ebx,2
;
; {
; k=a % i;
;
?live1@672: ; EBX = i, EDI = ts
@18:
mov eax,ebx
xor edx,edx
push edx
push eax
mov eax,dword ptr [ebp-8]
mov edx,dword ptr [ebp-4]
call __llumod ;最后跑到这个函数里去了,这个函数内部很复杂。
mov esi,eax
inc ebx
cmp ebx,100000000
jb short @18
;
; }
;
; printf("%lu\n", k);
;
?live1@688: ; ESI = k, EDI = ts
push esi
push offset s@+204
call _printf
add esp,8
;
; printf("用时:%lu\n", GetTickCount() - ts);
;
call GetTickCount
sub eax,edi
push eax
push offset s@+209
call _printf
add esp,8
95533 2003-04-16
  • 打赏
  • 举报
回复
呵呵,高手们都闲的搞这个了。
有空看看小弟的问题啊!
NowCan 2003-04-16
  • 打赏
  • 举报
回复
呵呵,谢拉。我知道VC下差别不大,只是不知道BCB是怎么回事。
liangbch 2003-04-16
  • 打赏
  • 举报
回复
关于比 int 型号更大的数的四则运算,我早在1996年,就分析过(使用turbo 2.0的编译器),分析的方法为用debug调试exe文件,当时 int 位16bit,long 型为32bit, 在做一个大数相乘的程序时,我发现long 型 数的计算速度比int 型慢的多,遂分析了一下long 型的算法问题,将那个程序的核心部分(往往是多层循环的内循环)用汇编改写,速度提高了60倍。
如今在vc环境下,则有更简单的方法,调试时打开反汇编窗口单步执行就可以了。
我常用的__int64 型的运算有这样的特点,如计算 c=a * b ,a=c / b 则a,b 不超过2^32 次方, 这时用汇编书写和c书写程序程序运行效率差别很小,近期很少做用汇编语言优化和核心代码的事情了。
 在vc下int64 型的计算速度和 int 相差不大,你可以用VC来试一试.
  
NowCan 2003-04-15
  • 打赏
  • 举报
回复
up
ccrun.com 2003-04-15
  • 打赏
  • 举报
回复
关注。
NowCan 2003-04-14
  • 打赏
  • 举报
回复
大家可以用VC等编译器编译对比看看。
gdyt007 2003-04-14
  • 打赏
  • 举报
回复
看看!!!呵呵!
NowCan 2003-04-14
  • 打赏
  • 举报
回复
up!
NowCan 2003-04-14
  • 打赏
  • 举报
回复
plainsong(伤心的风) :会不会VC6里的__int64是个类?
jishiping 2003-04-14
  • 打赏
  • 举报
回复
上面的话,我的意思是说这样的:
int num=0;
DWORD dwTick1 = GetTickCount();
for(int n=0; n<100000; n++)
num++;
DWORD dwTick2 = GetTickCount();
printf("Time=%lums", dwTick2-dwtick1);

如果这样的话,因为这个num没有真正使用,所以上面的循环,就被优化跳过去了(
没有执行)。但是如果你将最后一句改成:
printf("num=%d Time=%lums", num, dwTick2-dwtick1);
这样的话,因为真正用到了num,编译器就不会跳过循环了。

短歌如风 2003-04-14
  • 打赏
  • 举报
回复
如果编译器改用FPU去实现64位整数的话就会快得多(会和加法一样)。在Delphi中有Comp类型,就是这种整数,C++ 中没有,不过我们可以用类和操作符重载自己实现一个。
NowCan 2003-04-14
  • 打赏
  • 举报
回复
VC 6不支持 k=sqrt((double)a); 中,(double)a这种语法(__int64不能转为double),所以编译通不过,为公平起见,没有测试。

-------------------------------------------
这到没有想到。那k=sqrt(a);能不能支持呢?
NowCan 2003-04-14
  • 打赏
  • 举报
回复
我的代码中确实没有直接使用运算后的值。
循环1000000000次执行++a;估计直接就成了a+=1000000000;

NowCan 2003-04-14
  • 打赏
  • 举报
回复
VC在打开速度优化后加法的时间为0?

你有没有使用运算后的值?如果没有使用,优化时可能跳过你的测试代码,因而时间为0。

---------------------------------------------
我也遇到过,就算你在加一层循环也是这样。因此怀疑是作弊了,也就是代码是被优化没了。可以看看汇编是什么样的。我没有这个功底。


SharpKing515 2003-04-14
  • 打赏
  • 举报
回复
UP。。。
xc2927 2003-04-14
  • 打赏
  • 举报
回复
关注
Taiji02 2003-04-14
  • 打赏
  • 举报
回复
P4 1.5G+128M+w2k server:
测试加法(小于2^32)
用时:9375
测试加法(大于2^32)
用时:9453
测试开方(小于2^32)
10000
用时:17469
测试开方(大于2^32)
207484
用时:17453
测试求余(小于2^32)
94967337
用时:3406
测试求余(大于2^32)
94967339
用时:41000
测试除法(小于2^32)
42
用时:3344
测试除法(大于2^32)
42
用时:39843
jishiping 2003-04-14
  • 打赏
  • 举报
回复
VC在打开速度优化后加法的时间为0?

你有没有使用运算后的值?如果没有使用,优化时可能跳过你的测试代码,因而时间为0。
加载更多回复(10)

13,824

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧