【发布时间】:2021-12-01 03:07:12
【问题描述】:
如果我有整数 N 我知道因式分解,将 1/N 计算为浮点数的最快(最有效)方法是什么?应该使用大浮点(或整数)算法。
我想在 C++ 中执行此操作(或在 Python 中进行实验运行)。
我的N 非常大,有千兆/兆位大小。生成的浮点 N 也应该具有很高的精度,与初始 N 的位大小大致相同。
需要精确的浮点值意味着如果我请求浮点精度Log2(N) 位,那么至少结果的所有95% 前导位都应该是精确的(所有位都与理想值相同)。
当然,如果它有助于和/或简化任务,则可以将4^Ceil(Log2(N)) / N 计算为整数除法,而不是浮点计算。对我来说,这两个任务(整数和浮点数)本质上是相同的,因为整数表示可以转换为浮点数,反之亦然。
一个重要的注意事项是,N 的因式分解只有很小的质因数,它们都是 32 位大小(当然最多可能是 64 位)。
我想知道是否对N 进行了因式分解以及因数很小的事实,它能否以某种方式帮助解决任务?
当然,我没有首先实现我自己的部门,而是尝试使用高度优化的GMP 库来完成这项任务,但它(据我所知)并没有使用N 已经被分解的事实。
任何人都可以建议我是否要为此实现自己的功能,只是为了通过实验确定它是否会比 GMP 更快,那么我应该使用哪种算法?
我发现这里可以使用 3 种算法 1) Long Division,这是一种学校级算法。 2)Barrett Reduction。 3)Montgomery Reduction.
其实我不知道其他算法。你能推荐其他的吗? Barrett 和 Montgomery 约简只有在相同的素因数重复多次时才有帮助,否则单次除法不值得 Barrett 和 Montgomery 所需的预先计算。
此外,Barrett/Montgomery 减少仍需要一次性计算 4^Ceil(Log2(N)) / PrimeDivisor。所以他们不会让你免于做长除法算法。
对于长除法算法,我将使用2^64 作为基础而不是基础10(就像在学校一样)。
我已经使用长除法和所有其他整数算术算法以及椭圆曲线算术实现了我自己的实验库。现在它是通用的,因此不比 GMP 快。现在我需要一个比 GMP 至少快几倍的特殊除法算法。
当然,在长除法中我可以使用蒙哥马利和巴雷特,因为在每一步都需要短除法(128 位整数除以 64 位整数),如果它有任何提升的话。
在长除法的每一步,我都可以使用Fast Fourier Transform 或Number Theoretic Transform 进行乘法运算。
以上是我所知道的唯一优化。还有其他可能的优化吗?或许FFT可以直接做除法(不只是乘法)?
【问题讨论】:
-
我建议你首先让你的算法产生正确的结果,不管它运行多慢。然后在它上面运行一个分析器,看看你需要注意的慢的部分在哪里。在没有看到实际代码的情况下很难给出关于性能的建议
-
@EyalK。当前的问题不是如何优化我所拥有的。我已经有了通用代码。但它并不比 GMP 的通用变体快,这是显而易见的。优化我当前算法的速度没有意义,因为通用解决方案不会比 GMP 更快。这里的问题是如何使用分解可行的事实来实现真正快速的算法。也许有人可以判断基于 FFT 的除法技术是否可用。我不需要比 GMP 快 2 倍的解决方案,我需要一些特殊的算法,如果分解有帮助的话,它会快 10-20 倍。
-
您应该删除“性能”标签并添加 FORTRAN。 FORTRAN 在数字方面一直很高效。可能有一个您可以使用的 C++ 库。如果不是 FORTRAN,Algol 语言也擅长数字运算。
-
@ThomasMatthews 通过添加
performance标签,我的意思是我需要一些高性能的算法,特别是比不考虑 N 分解的常规方法(如 GMP)更快。这个标签并不意味着有人应该帮助我在我现有的代码中做一些小的优化。换句话说,我需要一些出色的想法来实现良好和高性能的算法。也许Fortran实际上有这种基于因子的划分。 -
@Ripi2 例如,对于乘法,存在 FFT(傅里叶),它可以达到
O(N Log(N))时间,这比O(N^2)学校级算法要好得多,如果你有 Tera,这是一个非常巨大的改进位数。但 FFT 只对大数快速。也许类似地,对于长除法,存在比天真的长除法快得多的非常快的算法,但它只对非常大的数字才快。我只是不知道是否存在这种情况,但不久前我也不知道 FFT,但它确实存在。所以等待数学/算法大师回复!
标签: python c++ algorithm performance math