我正在使用 IPython 来计时一些简短的示例,然后我将尝试解释结果。
from gmpy2 import mpfr, get_context
get_context().precision=1000
a=mpfr(1);b=mpfr(3)
%timeit a/b
1000000 loops, best of 3: 669 ns per loop
%timeit a/3
1000000 loops, best of 3: 464 ns per loop
get_context().precision=10000
a=mpfr(1);b=mpfr(3)
%timeit a/b
100000 loops, best of 3: 12.9 µs per loop
%timeit a/3
1000000 loops, best of 3: 1.33 µs per loop
get_context().precision=100000
a=mpfr(1);b=mpfr(3)
%timeit a/b
1000 loops, best of 3: 505 µs per loop
%timeit a/3
100000 loops, best of 3: 8.13 µs per loop
请注意,随着精度的增加,运行时间的a/b
增加速度比a/3
. 计算时a/b
,MPFR 使用两个值的完整精度,运行时间(大致)为 O(n * ln(n))。在计算 时a/3
,MPFR 使用 3 的简短但精确的表示,并且运行时间(大致)为 O(n)。这解释了为什么a/b
比a/3
高精度慢。(n 是以位为单位的长度a
。)
当 Python 计算scale//3
时,它利用了 3 将适合单个digit
并且运行时间与scale
. 这实际上与计算相同,a/3
但由于底层 GMP 库比 Python 快,a/3
因此计算速度比scale//3
.
这是 Python 和 GMP 之间性能差异的简短示例。
from gmpy2 import mpz
scale = 10**100000
%timeit scale//3
10000 loops, best of 3: 162 µs per loop
scale = mpz(scale)
%timeit scale//3
100000 loops, best of 3: 19 µs per loop
当您比较和时,您正在衡量一个n
by n
Division 和 an n
by Division 之间的性能。(是位的长度,比 小得多。)当您比较和 'a/3' 时,您是在比较一个简单、直接的除法实现和一个高度优化的实现。k
a/b
a/3
n
a
k
n
scale//3
实现说明:在当前不稳定的开发分支中,直接a/3
调用mpfr_div_ui
。这消除了 MPFR 创建临时对象的过程。这提高了性能,如下所示。
from gmpy2 import mpfr, get_context
get_context().precision=1000
a=mpfr(1);b=mpfr(3)
%timeit a/b
1000000 loops, best of 3: 593 ns per loop
%timeit a/3
1000000 loops, best of 3: 231 ns per loop
get_context().precision=10000
a=mpfr(1); b=mpfr(3)
%timeit a/b
100000 loops, best of 3: 12.7 µs per loop
%timeit a/3
1000000 loops, best of 3: 927 ns per loop
get_context().precision=100000
a=mpfr(1);b=mpfr(3)
%timeit a/b
1000 loops, best of 3: 505 µs per loop
%timeit a/3
100000 loops, best of 3: 6.77 µs per loop