整数开根号果真慢过浮点?
org 100hmov esi,0xfffffff
ee:
lea eax,
cvtsi2sd xmm0,eax
addsd xmm0,
sqrtsd xmm1,xmm0
cvttsd2si eax,xmm1
dec esi
jnz ee
ret
db $1e8-$ dup 0
yy:
dq 2147483648.0
时间2.6s
http://bbs.emath.ac.cn/thread-1207-2-1.html好像都更慢,有更快的吗 至1fffffff是4.84
至fffffffff是37.08 空转2^32 = 3.83 更严重的是
//这个程序计算从1到0xFFFFFFFF的所有数的平方根,并全部打印
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
register unsigned int num = 1;
register unsigned int root = 1;
register unsigned int square = 0;
for( ; ; root++)
{
square += root << 1;
square--;
for( ; ; )
{
if(num == square)
{
#ifdef __DEBUG__
printf("square root of %d is %d\n", num, root);
#endif
num++;
break;
}
#ifdef __DEBUG__
printf("square root of %d is %d\n", num, root-1);
#endif
num++;
if(num == 0xFFFFFFFF)
{
return 0;
}
}
}
return 0;
}
或
org 100h
xor eax,eax
xor ecx,ecx
xor edx,edx
s1:
lea edx,
s2:
;do
inc eax
dec edx
jnz s2
inc cx
jnz s1
ret
跑了一分多钟(接近2)没结果 org 100h
xor eax,eax
xor ecx,ecx
xor edx,edx
s1:
lea edx,
s2:
;do
inc eax
dec edx
jnz s2
inc cx
jnz s1
ret 是3.78,上一层楼的不对 平方根算法主要有牛顿迭代法、二分查找法,对于整型来说,还有一种“移位相减”的硬件算法。
对于计算机来说,要看运行的平台,比如 CPU 支持哪些指令集,以及相关指令的时钟数;
还要看需求,比如说,是否短时间内反复调用?cache 是否对其有影响?
另外,对于某些特殊范围的入参,还可以有更快的版本,比如说,对于 \(\text{4 ~ 15}\) 内的 \(n\),用 \((n+15)\gg3\) 即可快速获取其平方根。 1楼的程序核心部分使用了SSE2指令SQRTSD,这条指令属于浮点指令,和普通的浮点指令比,SSE2指令的操作数在MMX或者XMM中,而普通浮点指令的操作数在浮点数栈中进行。
下面列出这段代码中使用的几条SSE2指令。
cvtsi2sd:
Convert Dword Integer to Scalar Double-Precision FP Value
ADDSD:
Add Scalar Double-Precision Floating-Point Values
CVTTSD2SI:
Convert with Truncation Scalar Double-Precision FP Value to Signed Integer
SQRTSD:
Compute Square Root of Scalar Double-Precision Floating-Point Value
liangbch 发表于 2014-7-3 11:06
1楼的程序核心部分使用了SSE2指令SQRTSD,这条指令属于浮点指令,和普通的浮点指令比,SSE2指令的操作数在M ...
程序是我写的,这个我懂(当然作为补充也无妨):) liangbch 发表于 2014-7-3 11:06
1楼的程序核心部分使用了SSE2指令SQRTSD,这条指令属于浮点指令,和普通的浮点指令比,SSE2指令的操作数在M ...
不过你如果能分析lea和add的妙处那最好
lea eax,
cvtsi2sd xmm0,eax
addsd xmm0,;2147483648.0 l4m2 发表于 2014-7-3 11:24
不过你如果能分析lea和add的妙处那最好
这又什么难以理解的?
cvtsi2sd 要求源操作数是带符号数,故当操作数>=$2^31$, cvtsi2sd不能按预期的方式工作。代码“lea eax,”将被开方数减去$2^31$,转化为浮点数后,使用代码“addsd xmm0," 又加上$2^31$来恢复到原始值。这样,当被开方数大于$2^31$时,也能工作了。
页:
[1]
2