Python MPFR除法比本机整数除法快吗?

Python MPFR除法比本机整数除法快吗?,python,mpfr,gmpy,Python,Mpfr,Gmpy,我一直认为整数除法比浮点除法快,但我做了一些测试,似乎证明了这一点 import gmpy2, time, math digits = 100000 scale = 10**digits # Decimal precision gmpy2.get_context().precision = int(math.log2(10) * digits) # Binary precision def start_timer(): global start_time start

我一直认为整数除法比浮点除法快,但我做了一些测试,似乎证明了这一点

import gmpy2, time, math

digits = 100000

scale = 10**digits  # Decimal precision
gmpy2.get_context().precision = int(math.log2(10) * digits)  # Binary precision

def start_timer():
    global start_time  
    start_time = time.time()

def print_timer():
    print("%s s" % (time.time() - start_time))

start_timer()
for i in range(1000):
    x = scale // 3
print_timer()

start_timer()
for i in range(1000):
    x = gmpy2.mpfr(1) / 3
print_timer()

start_timer()
for i in range(1000):
    x = gmpy2.mpfr(1) / gmpy2.mpfr(3)
print_timer()
整数除法耗时0.17秒,mpfr除法耗时0.06秒,两个浮点数之间的除法耗时15.56秒

我的问题是:
  • 我是否正确设置了此测试
  • mpfr部门真的比本地部门更优化吗
  • 涉及浮点数和整数的除法比涉及两个浮点数的除法快得多吗

  • 在CPU上,浮点除法通常比整数除法快。有人可能会推测,这与FPU为此操作进行了更优化有关,或者浮点表示使除法更容易。但不管是什么原因都改变不了事实。最后,对你的第二个和第三个问题获得具体答案的唯一方法就是测试它。是的,你的测试在我看来还行


    如果我不得不大胆猜测,我认为将MPFR数除以整数的情况更快,因为GMP在计算除法时可以利用其有限的精度优势。

    浮点除法通常比CPU上的整数除法更快。有人可能会推测,这与FPU为此操作进行了更优化有关,或者浮点表示使除法更容易。但不管是什么原因都改变不了事实。最后,对你的第二个和第三个问题获得具体答案的唯一方法就是测试它。是的,你的测试在我看来还行


    如果我不得不大胆猜测,我认为将MPFR数除以整数的情况更快,因为GMP在计算除法时可以利用其有限的精度优势。

    我使用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将适合单个
    数字
    ,并且运行时间在
    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
    
    当您比较
    a/b
    a/3
    时,您是在测量
    n
    n
    划分和
    n
    k
    划分之间的绩效。(
    n
    a
    的长度,以位为单位,
    k
    n
    小得多)当您比较
    scale//3
    和'a/3'时,您是在比较简单、直接的除法实现和高度优化的实现

    实现说明:在当前不稳定的开发分支中,
    a/3
    直接调用
    mpfr\u div\u 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
    

    我用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将适合单个
    数字
    ,并且运行时间在
    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
    
    当您比较
    a/b
    a/3
    时,您是在测量
    n
    n
    划分和
    n
    k
    划分之间的绩效。(
    n
    a
    的长度,以位为单位,
    k
    n
    小得多)当您比较
    scale//3
    和'a/3'时,您是在比较简单、直接的除法实现和高度优化的实现

    实现说明:在当前不稳定的开发分支中,
    a/3
    直接调用
    mpfr\u div\u 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
    

    关于gnumpfr实现的一个注意事项(我是MPFR开发人员,但我没有真正研究除法):选择最佳的乘法和除法算法非常困难,因为有各种参数(输入和输出的精度,以及输入是否可以用更小的精度表示,特别是因为后面的零),有些情况可能比其他情况更难舍入。此外,算法因此可能会从一个版本更改为另一个版本,im