[英]Are C/C++ library functions and operators the most optimal ones?
因此,在分而治之课程中,我们被教导:
现在,给定2个正整数a和b是operator::*
比karatsuba(a,b)
快karatsuba(a,b)
或者pow(a,b)
比
int fast_expo(int Base, int exp)
{
if (exp == 0) {
return 1;
}
if (exp == 1) {
return Base
}
if (exp % 2 == 0) {
return fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
}
else {
return base * fast_expo(Base, exp / 2) * fast_expo(Base, exp / 2);
}
}
我问这个问题是因为我想知道它们是否只是出于教学目的,或者它们是否已经以C / C ++语言实现
唐津乘法是用于大整数的一种特殊技术。 它不能与将基本类型(例如int
和double
操作数相乘的内置C ++ *
运算符相提并论。
要使用唐津(Karatsuba),您必须使用至少由8个单词组成的多精度整数。 (如果是64位字,则为512位)。 根据对该问题的公认答案,唐津羽场变得有利的收支平衡点在8到24个机器单词之间。
与一对double
类型的浮点操作数一起使用的pow
函数不能与您的fast_expo
,后者与int
类型的操作数一起使用。 它们是具有不同要求的不同功能。 使用pow
,您可以计算5的立方根: pow(5, 1/3.0)
。 如果那是您想要计算的,那么无论多快, fast_expo
都没有用。
不能保证编译器或C库的pow
绝对是您的计算机对两个双精度浮点数求幂的最快方法。
浮点数的优化声明可能很棘手,因为经常会发生“相同”函数的多个实现在最后一位没有给出完全相同的结果的情况。 您可能可以编写一个快速的my_pow
,该精度仅好于五个精度的十进制数字,并且在您的应用程序中,近似值可能my_pow
。 你打败图书馆了吗? 几乎不; 您的快速功能不符合将其替换为库中pow
资格的要求。
operator::*
和其他标准运算符通常映射到硬件提供的原语。 万一此类原语不存在(例如,IA32上的64位long long
),编译器会对其进行仿真,但会降低性能(gcc在libgcc
中libgcc
)。
与std::pow
相同。 它是标准库的一部分,没有强制以某种方式实现。 GNU libc将pow(a,b)
为exp(log(a) * b)
。 exp
和log
相当长,在编写时要考虑IEEE754浮点以实现最佳性能。
至于你的建议:
小号唐津乘法不值得。 处理器提供的乘法器指令已经针对所使用的标准数据类型的速度和功耗进行了优化。 有了更大的数字,即寄存器容量的10到20倍, 它就会开始获得回报 :
在GNU MP Bignum库中 ,过去的默认
KARATSUBA_THRESHOLD
用于非模数乘法(即,当n>=32w
且通常w=32
时使用Karatsuba); 模幂的最佳阈值往往要高得多。 在现代CPU上,软件中的Karatsuba对于诸如PDS 256上的ECDSA之类的东西(n=256
,w=32
或w=64
)来说往往是无益的,但是可以想象得到,对于RSA中使用的更宽的模数有用。
这是一个包含乘法算法 ,GNU MP使用及其各自阈值的列表。
快速取幂不适用于非整数幂,因此它实际上不能与pow
相提并论。
检查操作速度的一种好方法是对其进行测量。 如果您进行了十亿次左右的计算,然后查看执行了多少时间,那么答案就在那里。
要注意的一件事。 我导致相信%相当昂贵。 有一种更快的方法来检查某物是否可被2整除:
check_div_two(int number)
{
return ((number>>1) & 0x01);
}
这样,您只是做了一点移动,并与蒙版进行了比较。 我认为这是一个便宜些的操作。
内置类型的*
运算符几乎肯定会实现为单个CPU乘法指令。 因此,最终这是一个硬件问题,而不是语言问题。 在没有直接硬件支持的情况下, 可能会生成更长的代码序列(可能是函数调用)。
可以肯定地说,芯片制造商(英特尔,AMD等)花费了大量精力使算术运算尽可能高效。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.