CPU /编程语言使用哪种取幂算法?

时间:2015-04-01 00:55:37

标签: c algorithm math compiler-construction cryptography

我一直在学习更快的取幂算法(k-ary,滑动门等),并且想知道在CPU /编程语言中使用哪些算法? (我对这是否发生在CPU或编译器中都很模糊)

只是为了踢,这是最快的?

关于广度的编辑:它有意广泛,因为我知道有很多不同的技术可以做到这一点。已检查的答案符合我的要求。

1 个答案:

答案 0 :(得分:3)

我假设您对实现可以在HLL的标准数学库中找到的取幂函数感兴趣,特别是C / C ++。其中包括函数exp()exp2()exp10()pow(),以及单精度对应expf()exp2f(),{{ 1}}和exp10f()

您提到的取幂方法(例如k-ary,滑动窗口)通常用于加密算法,例如RSA,它是基于取幂的。它们通常不用于通过powf()math.h提供的取幂函数。标准数学函数(如cmath)的实现细节有所不同,但常见的方案遵循三个步骤:

  1. 将函数参数减少为主近似值 间隔
  2. 在初级近似区间上近似合适的基函数
  3. 将主要间隔的结果映射回函数的整个范围
  4. 辅助步骤通常是处理特殊情况。这些可能涉及特殊的数学情况,如exp(),或特殊的浮点操作数,如NaN(非数字)。

    以下log(0.0)的C99代码以示例性方式显示了具体示例的那些步骤。首先将expf(float)参数拆分为a = e r * 2 i ,其中exp(a)是整数且{{ 1}}在[log(sqrt(0.5),log(sqrt(2.0)]中,是主要的近似区间。在第二步中,我们现在用多项式逼近e r 。这样的近似可以根据各种设计标准设计,例如最小化绝对误差或相对误差。多项式可以用各种方式进行评估,包括Horner方案和Estrin方案。

    下面的代码采用一种非常常见的方法,采用最小极大近似,最小化整个近似间隔的最大误差。用于计算这种近似的标准算法是Remez算法。评估是通过霍纳的计划;使用i增强了评估的数字准确性。

    这个标准的数学函数实现了所谓的融合乘法加法或FMA。这会在添加期间使用完整产品r计算fmaf(),并在结尾处应用单个舍入。在大多数现代硬件上,例如GPU,IBM Power CPU,最近的x86处理器(例如Haswell),最近的ARM处理器(作为可选扩展),这直接映射到硬件指令。在缺少这种指令的平台上,a*b+c将映射到相当慢的仿真代码,在这种情况下,如果我们对性能感兴趣,我们就不会想要使用它。

    最后的计算是乘以2 i ,其中C和C ++提供函数a*b。在“工业强度”库代码中,通常使用机器特定的习惯用法,其利用了fmaf()的IEEE-754二进制算法。最后,代码清理溢出和下溢的情况。

    x86处理器内的x87 FPU有一条指令ldexp(),可以在[-1,1]上计算2 x -1。这可用于计算floatF2XM1的第二步。在第三步中有一条指令exp()用于乘以2 i 。实现exp2()本身的常用方法是使用有理或多项式近似的微码。请注意,x87 FPU主要用于传统支持。在现代x86平台上,库通常使用基于SSE的纯软件实现和类似于下面所示的算法。有些将小表与多项式近似结合起来。

    FSCALE可以在概念上实现为F2XM1,但是当pow(x,y)接近统一且exp(y*log(x))大小时,这会严重损失准确性,以及对C / C ++标准中规定的众多特殊情况的错误处理。解决准确性问题的一种方法是以某种形式的扩展精度计算x和产品y。细节将填写一个完整,冗长的单独答案,我没有代码方便地演示它。在各种C / C ++数学库中,log(x)y*log(x))由单独的代码路径计算,该路径应用“square-and-multiply”方法,逐位扫描整数的二进制表示指数。

    pow(double,int)