Bignum 实现有效地添加小整数

Posted

技术标签:

【中文标题】Bignum 实现有效地添加小整数【英文标题】:Bignum implementation that has efficient addition of small integers 【发布时间】:2009-12-02 07:33:27 【问题描述】:

我一直在使用 python 的原生 bignums 作为算法,并决定尝试通过将其转换为 C++ 来加速它。当我使用 long long 时,C++ 比 python 快大约 100 倍,但是当我在 C++ 中使用 GMP 绑定时,它只比 python 快 10 倍(对于适合 long long 的相同情况)。

有没有更好的 bignum 实现来做大量的小加法?例如,我们有一个大数字 N,我们将添加很多小的 +1、+21、+1 等,并且每隔一段时间添加另一个大数字 M?

【问题讨论】:

【参考方案1】:

GMP 库本身有一个fast short integer add to MPZ routine

void mpz_add_ui (mpz_t rop, mpz_t op1, unsigned long int op2)

我不知道 gmpy 是否使用它,但如果它确实尝试将普通 python int 添加到 mpz 与将 mpz 添加到 mpz 并查看它是否更快。

编辑

我尝试了一些基准测试,发现它没有任何区别

$ python -m timeit -c 'from gmpy import mpz
> a=mpz(10**1000)' 'a+1'
100000 loops, best of 3: 5.4 usec per loop

$ python -m timeit -c 'from gmpy import mpz
a=mpz(10**1000); b=mpz(1)' 'a+b'
100000 loops, best of 3: 5.5 usec per loop

所以我猜 gmpy 不使用 mpz_add_ui,因为我真的希望它会快很多。

【讨论】:

有趣。我正在使用算术运算的 C++ 重载,也许这些 C++ 绑定也没有使用这种快速方法。明天我会做一些测试。谢谢!【参考方案2】:

您是否进行了分析? Python 和 C++ 整个 应用程序。这样您就知道您确实需要这种额外的速度。

试试 Python 3k,它现在实现了任意长度的整数!

【讨论】:

当唯一的变化是从多头到 GMP MPZ 时,整个程序都会出现这种减速。谢谢。 “Python 3k 现在有任意长度的整数”是什么意思? Python 从至少 2.5 版(可能更早)开始就有任意长度的整数。【参考方案3】:

(注意:我帮助维护 GMPY,并且我在最新版本中实施了很多优化。)

GMPY v1.11 在向 mpz 添加一个小数字时确实使用了mpz_add_ui。在处理小数字时,最新版本的 GMPY 也比以前的版本快 25%。

With GMPY 1.04
$ py26 -mtimeit -s "import gmpy;a=gmpy.mpz(10**1000)" "a+1"
10000000 loops, best of 3: 0.18 usec per loop
$ py26 -mtimeit -s "import gmpy;a=gmpy.mpz(10**1000);b=gmpy.mpz(1)" "a+b"
10000000 loops, best of 3: 0.153 usec per loop

With GMPY 1.11
$ py26 -mtimeit -s "import gmpy;a=gmpy.mpz(10**1000)" "a+1"
10000000 loops, best of 3: 0.127 usec per loop
$ py26 -mtimeit -s "import gmpy;a=gmpy.mpz(10**1000);b=gmpy.mpz(1)" "a+b"
10000000 loops, best of 3: 0.148 usec per loop

由于将 Python int 转换为 long 并调用 mpz_add_ui 比将 Python int 转换为 mpz 更快,因此具有适度的性能优势。如果长时间调用 GMP 函数与本地操作相比,性能损失 10 倍,我不会感到惊讶。

你能把几个小数累加成一长一长,然后一次把它们加到你的大数上吗?

【讨论】:

是的,我一直在考虑编写自己的课程来积累小数字并不经常将它们添加到大数字中。感谢您提供有关 GMPY 1.11 的说明。

以上是关于Bignum 实现有效地添加小整数的主要内容,如果未能解决你的问题,请参考以下文章

输入N对位数不超过1000的正整数,求它们的和。 (编程使用struct创建一个bigNum类型?

有效地实现下限/欧几里得整数除法

关于perl bignum模块用法

将两个整数x和y有效地转换为浮点数x.y

如何有效地将节点添加到段树中以进行最小范围查询?

在python中使用两个加法运算符来添加两个整数是不是有效? [复制]