经过许多个月的艰辛努力,我自己独立开发的高精度算术库(BCMP)终于可以告一段落了。另外,由我自己独创的对数log(x)算法也已经完成。测试报告显示,这个算法的性能是非常令人振奋的,在100-10000位精度下,可比现在最快软件Mathematica[注9]快2.8到8倍。
BCMP和GMP[注1]类似,利用BCMP可以计算任意精度整数和浮点数的算术运算,包括加,减,乘,除,开平方等。和GMP类似,我开发这套大数库的主要目标为追求极致的性能。现在,这一目标已基本达到。在中等精度(1万位十进制)以下,BCMP在大多数情况下,显著领先于GMP。当精度更高时,bcmp则慢于GMP,这是因为,大数运算库的关键是乘法,而不同大小的操作数需要使用不同的算法,没有一种算法可以适应于任意情况。BCMP中实现了basecase乘法[注2],karatsuba乘法[注3],Toom-Cook[注4]系列乘法,而尚未实现适应于操作数很大的SSA[注5]算法,或者FFT[注6]算法和NTT[注7]算法。和GMP不同,BCMP提供了2套接口,第一套接口支持2进制运算,内部表示采用\(2^{30}\)进制,另一套接口支持10进制运算,内部表示采用\(10^9\)进制。BCMP计划同时支持32位和64位方式编译,也计划同时支持在windows下编译和Linux下编译。现在已实现32位模式下的用Visual Studio编译,今后将逐步完善其他功能。
BCMP主要使用C语言和汇编语言开发,为了实现极高的性能,使用了大量的汇编代码,对关键部分做了精心的优化,除了普通的汇编指令外,还大量使用SSE2,SSE4和少数AVX2指令。
新的任意精度对数函数算法是我独创的,不同于任何一个公开发表的算法。新算法基于质数分解和比特突发算法,大大加速了计算速度,从算法复杂度来说,它和目前最快的算法AGM算法[注8]有相同的复杂度,都是O(log(P)M(P)),p为精度,其中M(P)代表两个P位整数相乘所需要的基本运算的次数。但是我的算法有更小的常数因子,速度更快。下表列出了几个最著名数学软件和大数库与BCMP在计算log(x)的性能对比结果。从这个表中可以看出,当精度为100到10000位时,我的新算法是MPFR[注11]的3.7到8.6倍
测试平台:
处理器: Intel(R) Core(TM) i7-2600K CPU @3.40GH
操作系统: Windows7 32-bit
Maple[注10] 版本:17.0
Mathematica版本: 10.3.0 32-bit
Pari[注12]版本: 2.9.3
mpfr版本:3.1.6
位数 | 时间,单位为毫秒 | |||||
Maple | Mathematica | Pari | MPFR | BCMP_log1 | BCMP_log2 | |
20 | 0.029941 | 0.00247424 | 0.003114 | 0.004833 | 0.008654 | 0.000762 |
30 | 0.040354 | 0.00305579 | 0.003744 | 0.005667 | 0.008218 | 0.000975 |
40 | 0.043768 | 0.003999 | 0.004687 | 0.006456 | 0.010237 | 0.001043 |
50 | 0.045405 | 0.00464357 | 0.005267 | 0.006782 | 0.010515 | 0.001217 |
60 | 0.061336 | 0.00551004 | 0.007068 | 0.008939 | 0.012052 | 0.002432 |
70 | 0.063722 | 0.00660306 | 0.008129 | 0.009373 | 0.012467 | 0.002622 |
80 | 0.06523 | 0.00748533 | 0.008918 | 0.010451 | 0.014011 | 0.002847 |
90 | 0.067488 | 0.00873332 | 0.009401 | 0.010859 | 0.013989 | 0.002967 |
100 | 0.069835 | 0.00976343 | 0.011404 | 0.012145 | 0.017113 | 0.003194 |
125 | 0.072167 | 0.0121835 | 0.013434 | 0.014376 | 0.020085 | 0.003843 |
158 | 0.079578 | 0.0186991 | 0.020295 | 0.018568 | 0.026015 | 0.004825 |
199 | 0.084953 | 0.0257783 | 0.027464 | 0.023096 | 0.032686 | 0.005604 |
251 | 0.101058 | 0.0337484 | 0.039437 | 0.030076 | 0.041313 | 0.006338 |
316 | 0.111391 | 0.0496319 | 0.057234 | 0.03874 | 0.057398 | 0.008075 |
398 | 0.125592 | 0.0655544 | 0.090215 | 0.054713 | 0.076384 | 0.009971 |
501 | 0.140205 | 0.0873334 | 0.126219 | 0.076801 | 0.100851 | 0.012947 |
630 | 0.169863 | 0.143491 | 0.173471 | 0.1227 | 0.126775 | 0.025564 |
794 | 0.201257 | 0.213486 | 0.262401 | 0.192741 | 0.175562 | 0.022624 |
1000 | 0.26965 | 0.331134 | 0.378275 | 0.29729 | 0.260477 | 0.041692 |
1258 | 0.344599 | 0.4512 | 0.545905 | 0.425357 | 0.321757 | 0.056777 |
1584 | 0.437988 | 0.615793 | 0.836217 | 0.671066 | 0.504561 | 0.077545 |
1995 | 0.570668 | 0.871282 | 1.219222 | 1.042976 | 0.671209 | 0.133183 |
2511 | 0.807129 | 1.20226 | 1.723848 | 1.448282 | 0.983084 | 0.190615 |
3162 | 1.07266 | 1.68033 | 2.561828 | 2.257336 | 1.489376 | 0.273305 |
3981 | 1.47754 | 2.42274 | 3.66907 | 2.959093 | 2.155975 | 0.510987 |
5011 | 2.15234 | 3.27768 | 5.208427 | 3.788049 | 3.193957 | 0.727249 |
6309 | 2.96615 | 4.7273 | 7.723928 | 5.709551 | 4.507839 | 1.019573 |
7943 | 4.0625 | 6.69787 | 11.071721 | 7.894751 | 6.753858 | 1.748821 |
10000 | 6.33854 | 9.14068 | 15.950279 | 10.198301 | 9.649934 | 2.538205 |
17782 | 15.1146 | 21.4501 | 38.916218 | 23.862088 | 23.569465 | 6.929607 |
31622 | 42.25 | 56.5504 | 94.352581 | 68.980759 | 62.309453 | 18.861327 |
56234 | 681 | 117.001 | 207.879794 | 131.337302 | 146.628323 | 45.943156 |
100000 | 2012.67 | 260.002 | 587.256462 | 296.982964 | 364.771994 | 117.998387 |
性能对比折线图,以mpfr为基准,令mpfr的运行时间为1,值越小越好。
性能对比折线图2,去掉Maple的测试结果,仍以mpfr为基准,值越小越好。
说明:BCMP用两种方法实现了两个版本的log函数,第一个使用AGM算法,在上表中标记为BCMP_log1, 第二个使用新算法,标记为BCMP_log2
测试代码下载:
mathematica,maple,pari,mpfr,bcmp,time
测试结果下载:
test_result
更多的任意精度浮点软件性能比较,请参阅Comparison of multiple-precision floating-point software
1.GMP是一个用于任意精度算术的免费库,用于对有符号整数,有理数和浮点数进行操作。GMP的主要目标应用是密码应用和研究,互联网安全应用和计算机代数系统。GMP是一个非常优秀的大数库,已有26年的历史。GMP的作者曾宣称,GMP是地球上最快的大数库,原文“the fastest bignum library on the planet!”。因为GMP非常快,所以很多应用软件使用GMP,如计算机代数系统Mathematica和Maple中的整数运算就是调用GMP来实现的。
关于GMP更多的信息,请参阅https://gmplib.org 和 https://en.wikipedia.org/wiki/GNU_Multiple_Precision_Arithmetic_Library
2.basecase乘法,也叫长乘法(Long multiplication),请参阅 https://en.wikipedia.org/wiki/Multiplication_algorithm
3.Karatsuba乘法,也称Karatsuba算法,这个算法由Anatoly Karatsuba在1960年发现的, 是一种比长乘法更快的算法,请参阅https://en.wikipedia.org/wiki/Karatsuba_algorithm。
4.Toom–Cook乘法,狭义的Toom-Cook算法指Toom-3算法,可以看做是Karatsuba乘法的推广。广义的Toom-Cook乘法包括Toom4,Toom5等一大类算法。这个算法最早由俄罗斯数学家Andrei Toom提出,而Stephen Cook(是美国和加拿大计算机科学和数学家,图灵奖的获得者)给出更清晰的描述,请参阅维基百科https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
5.SSA算法指Schönhage–Strassen algorithm ,他是德国数学家和计算机科学家Arnold Schönhage和德国数学家Volker Strassen在1971开发出来的一个算法。关于这个算法的更多信息,请参阅维基百科https://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm 和百度百科https://baike.baidu.com/item/SSA/18691142,原始论文请参阅《A GMP-based Implementation of Schönhage-Strassen’s Large Integer Multiplication Algorithm》
6.FFT指快速傅里叶变换(fast Fourier transform),是基于复数的一种线性变换,这个算法在电子技术领域得到极其广泛的应用,是20世纪10大算法之一。另外,这个算法可用来计算大数乘法。关于FFT的更多信息,请参阅 https://en.wikipedia.org/wiki/Fast_Fourier_transform。关于20世纪10大算法,请参阅http://science.dataguru.cn/article-9643-1.html
7.NTT指数论变换(Number-theoretic transform),它是FFT推广到有限域上的一种变换算法,和FFT不同,他不使用复数域上的加,减和乘法,而是使用模算术。apfloat中的大数乘法用的就是NTT算法。感兴趣的读者可以参阅蒋增荣的《数论变换》或者孙琦的《快速数论变换》等书。
8.AGM指算法几何平均数,关于这个算法的描述请参阅澳大利亚数学家和计算机科学家Richard P. Brent《Fast Algorithms for High-Precision Computation of Elementary Functions》和的Borwein兄弟的《The arithmetic-geometricmean and fast computation of elementary functions》和。Borwein兄弟都是数学家,他们出生在苏格兰。
9.Mathematica 是一款功能强大的科学计算软件,和MATLAB、Maple 并称为三大数学软件。请参阅百度百科
https://baike.baidu.com/item/Mathematica
10.Maple和Mathematica类似,也是一款功能强大的科学计算软件。请参阅百度百科https://baike.baidu.com/item/maple/2306572
11.MPFR是基于GMP的一套2进制浮点库,请参阅维基百科https://en.wikipedia.org/wiki/GNU_MPFR
12.PARI/GP是一个计算机代数系统,请参阅维基百科https://en.wikipedia.org/wiki/PARI/GP