gmpy2
比mpmath
这种类型的计算要快得多。以下代码在我的机器上运行速度提高了大约 12 倍。
import numpy as np
import gmpy2 as mp
import time
a = np.linspace(0, 100e-2, 100)
b = np.linspace(0, np.pi)
c = np.arange(30)
t = time.time()
M = np.ones([len(a), len(b), len(c)])
A, B = np.meshgrid( a, b, indexing = 'ij' )
temp = A**2+B
temp = np.reshape(temp, [len(a), len(b), 1])
temp = np.repeat(temp, len(c), axis=2)
M *= temp
print 'part1:', time.time() - t
t = time.time()
temp = np.array([mp.factorial(x) for x in c])
temp = np.reshape(temp, [1, 1, len(c)])
temp = np.repeat(temp, len(a), axis=0)
temp = np.repeat(temp, len(b), axis=1)
print 'part2 so far:', time.time() - t
M *= temp
print 'part2:', time.time() - t
t = time.time()
mpmath
是用 Python 编写的,通常使用 Python 的本机整数进行计算。如果gmpy2
可用,它将使用由 提供的更快的整数类型gmpy2
。如果您只需要 直接提供的功能之一gmpy2
,那么gmpy2
直接使用通常会更快。
更新
我进行了一些实验。实际发生的事情可能不是你所期望的。计算temp
时,值可以是整数(math.factorial
、gmpy.fac
或gmpy2.fac
)或浮点值(gmpy2.factorial
、mpmath.fac
)。当numpy
computes时M *= temp
,所有的值temp
都被转换为 64 位浮点数。如果该值是整数,则转换会引发溢出错误。如果该值是浮点数,则转换返回无穷大。您可以通过更改c
为np.arange(300)
并在最后打印来看到这一点M
。如果你使用gmpy.fac
or math.factorial
,你会得到 and OverflowError
。如果您使用mpmath.factorial
or gmpy2.factorial
,您将不会得到 anOverflowError
但结果M
将包含无穷大。
如果您试图避免OverflowError
,则需要temp
使用浮点值进行计算,以便转换为 64 位浮点数将导致无穷大。
如果您没有遇到OverflowError
,那么math.factorial
是最快的选择。
如果您试图避免两者OverflowError
和无穷大,那么您将需要在整个过程中使用 thempmath.mpf
或gmpy2.mpfr
浮点类型。(不要尝试使用gmpy.mpf
。)
更新#2
这是一个使用gmpy2.mpfr
200 位精度的示例。使用c=np.arange(30)
,它比您的原始示例快约 5 倍。我使用它来展示它,c = np.arange(300)
因为它会生成一个OverflowError
或无穷大。较大范围的总运行时间与您的原始代码大致相同。
import numpy as np
import gmpy2
import time
from gmpy2 import mpfr
gmpy2.get_context().precision = 200
a = np.linspace(mpfr(0), mpfr(1), 100)
b = np.linspace(mpfr(0), gmpy2.const_pi())
c = np.arange(300)
t = time.time()
M = np.ones([len(a), len(b), len(c)], dtype=object)
A, B = np.meshgrid( a, b, indexing = 'ij' )
temp = A**2+B
temp = np.reshape(temp, [len(a), len(b), 1])
temp = np.repeat(temp, len(c), axis=2)
M *= temp
print 'part1:', time.time() - t
t = time.time()
temp = np.array([gmpy2.factorial(x) for x in c], dtype=object)
temp = np.reshape(temp, [1, 1, len(c)])
temp = np.repeat(temp, len(a), axis=0)
temp = np.repeat(temp, len(b), axis=1)
print 'part2 so far:', time.time() - t
M *= temp
print 'part2:', time.time() - t
t = time.time()
免责声明:我坚持gmpy2
.