이 계산 유형에 대해 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
는 파이썬으로 작성된 정상적으로의 계산에 파이썬의 기본 정수를 사용합니다.
gmpy2
을 사용할 수있는 경우
gmpy2
에서 제공하는 더 빠른 정수 유형을 사용합니다.
gmpy2
으로 직접 제공되는 기능 중 하나가 필요하다면
gmpy2
을 직접 사용하는 것이 일반적으로 더 빠릅니다.
업데이트 나는 몇 가지 실험을 달렸다. 실제로 일어나는 일은 당신이 기대하는 바가 아닐 수도 있습니다. temp
을 계산할 때 값은 정수 (math.factorial
, gmpy.fac
또는 gmpy2.fac
)이거나 부동 소수점 값 (gmpy2.factorial
, mpmath.fac
) 일 수 있습니다. numpy
이 M *= temp
이라고 계산하면 temp
의 모든 값이 64 비트 부동 소수점으로 변환됩니다. 값이 정수인 경우 변환은 OverflowError를 발생시킵니다. 값이 부동 소수점 수이면 변환은 무한대를 반환합니다. c
을 np.arange(300)
으로 변경하고 마지막에 M
을 인쇄하여 확인할 수 있습니다. gmpy.fac
또는 math.factorial
을 사용하는 경우 OverflowError
이 표시됩니다. mpmath.factorial
또는 gmpy2.factorial
을 사용하는 경우 OverflowError
이 표시되지 않지만 그 결과로 M
에는 무한대가 포함됩니다.
OverflowError
을 피하려면 부동 소수점 값을 사용하여 temp
을 계산해야합니다. 따라서 64 비트 부동 소수점으로 변환하면 무한대가됩니다.
OverflowError
이 발생하지 않으면 math.factorial
이 가장 빠릅니다.
OverflowError
과 무한대를 모두 피하려면, mpmath.mpf
또는 gmpy2.mpfr
부동 소수점 유형 중 하나를 사용해야합니다. (gmpy.mpf
을 사용하지 마십시오.)
업데이트 # 2
여기서 200 비트의 정밀도로 gmpy2.mpfr
를 사용하는 예이다. c=np.arange(30)
을 사용하면 원래 예제보다 ~ 5 배 빠릅니다. OverflowError
또는 무한대를 생성하기 때문에 c = np.arange(300)
을 사용하여 보여줍니다. 큰 범위의 총 실행 시간은 원래 코드와 거의 같습니다.
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
을 유지한다.
와우! 12 배! 나는 gmpy (이전에'MPMATH_NOGMPY'를 설정 했었습니다)로 실행 시켰지만 기껏해야 40 %의 속도 향상 만했습니다. 또한, 내'mp.libmp.BACKEND'는'gmpy'가 아니며'gmpy2'가 아니라면 어떤 차이가 있습니까? – evan54
죄송합니다. 나는 잘못된 코드를 붙여 넣었다. 나는'gmpy2'를 직접 사용하고 있었다. 잠시 후에 답을 수정하겠습니다. 'gmpy2'는 MPFR (정확하게 반올림 한 실수 부동 소수점)과 MPC (정확한 반올림 된 부동 소수점) 임의 정밀도 라이브러리에 대한 완전한 액세스를 제공합니다. 오래된'gmpy'는 MPFR과 MPC를 지원하지 않습니다. – casevh
흠 ... 나는 당신이 만든 유일한 변화가 계승 함수가 사용된다는 것을 알아 차렸다. 내 코드가 느려지는 것은'mp * fx (x)'연산이 아닌 마지막'M * = temp'입니다. 이 경우 백엔드가 많이 중요합니까? – evan54