Вы можете использовать Numba или низкоуровневую вызываемую
Почти ваш пример
Я просто передаю функцию непосредственно в scipy.integrate.dblquad
вместо вашего метода, использующего лямбда-выражения для генерации функций.
import numpy as np
from scipy import integrate
from scipy.special import erf
from scipy.special import j0
import time
q = np.linspace(0.03, 1.0, 1000)
start = time.time()
def f(t, z, q):
return t * 0.5 * (erf((t - z) / 3) - 1) * j0(q * t) * (1 / (np.sqrt(2 * np.pi) * 2)) * np.exp(
-0.5 * ((z - 40) / 2) ** 2)
def lower_inner(z):
return 10.
def upper_inner(z):
return 60.
y = np.empty(len(q))
for n in range(len(q)):
y[n] = integrate.dblquad(f, 0, 50, lower_inner, upper_inner,args=(q[n],))[0]
end = time.time()
print(end - start)
#143.73969149589539
Это уже немного быстрее (143 против 151 с), но единственная польза — простой пример для оптимизации.
Простая компиляция функций с помощью Numba
Чтобы это запустить, вам дополнительно понадобятся Numba и numba-scipy. Целью numba-scipy является предоставление обернутых функций из scipy.special
.
import numpy as np
from scipy import integrate
from scipy.special import erf
from scipy.special import j0
import time
import numba as nb
q = np.linspace(0.03, 1.0, 1000)
start = time.time()
#error_model="numpy" -> Don't check for division by zero
@nb.njit(error_model="numpy",fastmath=True)
def f(t, z, q):
return t * 0.5 * (erf((t - z) / 3) - 1) * j0(q * t) * (1 / (np.sqrt(2 * np.pi) * 2)) * np.exp(
-0.5 * ((z - 40) / 2) ** 2)
def lower_inner(z):
return 10.
def upper_inner(z):
return 60.
y = np.empty(len(q))
for n in range(len(q)):
y[n] = integrate.dblquad(f, 0, 50, lower_inner, upper_inner,args=(q[n],))[0]
end = time.time()
print(end - start)
#8.636585235595703
Использование вызываемого объекта низкого уровня
Функции scipy.integrate
также предоставляют возможность передавать функцию обратного вызова C вместо функции Python. Эти функции можно написать, например, на C, Cython или Numba, которые я использую в этом примере. Основное преимущество заключается в том, что при вызове функции не требуется взаимодействие с интерпретатором Python.
Отличный ответ @Jacques Gaudin показывает простой способ сделать это, включая дополнительные аргументы.
import numpy as np
from scipy import integrate
from scipy.special import erf
from scipy.special import j0
import time
import numba as nb
from numba import cfunc
from numba.types import intc, CPointer, float64
from scipy import LowLevelCallable
q = np.linspace(0.03, 1.0, 1000)
start = time.time()
def jit_integrand_function(integrand_function):
jitted_function = nb.njit(integrand_function, nopython=True)
#error_model="numpy" -> Don't check for division by zero
@cfunc(float64(intc, CPointer(float64)),error_model="numpy",fastmath=True)
def wrapped(n, xx):
ar = nb.carray(xx, n)
return jitted_function(ar[0], ar[1], ar[2])
return LowLevelCallable(wrapped.ctypes)
@jit_integrand_function
def f(t, z, q):
return t * 0.5 * (erf((t - z) / 3) - 1) * j0(q * t) * (1 / (np.sqrt(2 * np.pi) * 2)) * np.exp(
-0.5 * ((z - 40) / 2) ** 2)
def lower_inner(z):
return 10.
def upper_inner(z):
return 60.
y = np.empty(len(q))
for n in range(len(q)):
y[n] = integrate.dblquad(f, 0, 50, lower_inner, upper_inner,args=(q[n],))[0]
end = time.time()
print(end - start)
#3.2645838260650635
person
max9111
schedule
07.04.2020
numpy
вопросов. - person hpaulj   schedule 04.04.2020quadpy
в stackoverflow.com/questions/60905349/ а>. Часто запрос рекомендаций других пакетов для решения проблемы не одобряется в SO. - person hpaulj   schedule 04.04.2020math.sqrt
иmath.exp
(иmath.erf
) быстрее, чем эквивалентыnp
. - person hpaulj   schedule 04.04.2020t
иz
фиксированы, не могли бы вы сделать то же самое с двумяquad
илиquad_vec
? В предыдущем вопросеquad_vec
на самом деле быстрее, чемquadpy
. - person hpaulj   schedule 04.04.2020quad
илиquad_vec
, но я понятия не имею, как использовать в моем случае. Буду признателен за любые предложения/помощь по этому поводу :) - person Shankar_Dutt   schedule 04.04.2020quadpy
. Как было предложено выше, может быть, использовать quad дважды или любым другим способом? - person Shankar_Dutt   schedule 05.04.2020f()
. Я предложил аналогичные вещи с вашим предыдущим вопросом 1d. Мы улучшаем этиquad
раза, либо делаяf()
быстрее, либо используя более умныйquad
(который может вызыватьf
меньше раз).quad_vec
повышает скорость, запрашивая уf
несколько значений одновременно. - person hpaulj   schedule 06.04.2020