Привет, я сейчас работаю в модуле Python для термодинамических равновесий фаз жидкости.Для этого мне нужно запрограммировать модели коэффициентов активности, такие как NRTL, которые включают в себя несколько сумм.Чтобы повысить производительность модуля, я попытался выполнить функцию jit с помощью numba:
@jit(cache=True)
def NRTL(X,T,g, alpha, g1):
'''
NRTL activity coefficient model.
input
X: array like, vector of molar fractions
T: float, absolute temperature in K.
g: array like, matrix of energy interactions in K.
g1: array_like, matrix of energy interactions in K^2
alpha: float, aleatory factor.
tau = ((g + g1/T)/T)
output
lngama: array_like, natural logarithm of activify coefficient
'''
tau = g + g1*T
tau /= T
nc=len(X)
G=np.exp(-alpha*tau)
lngama=np.zeros_like(X)
for i in range(nc):
SumC=SumD=SumE=0
for j in range(nc):
A=X[j]*G[i,j]
SumA=SumB=0
for k in range(nc):
SumA +=X[k]*G[k,j]
SumB +=X[k]*G[k,j]*tau[k,j]
SumC +=A/SumA*(tau[i,j]-SumB/SumA)
SumD+=X[j]*G[j,i]*tau[j,i]
SumE+=X[j]*G[j,i]
lngama[i]=SumD/SumE+SumC
return lngama
Я пробовал новые опции, как cython, но я не получаю такую хорошую производительность, как с jit numbas.
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False)
@cython.wraparound(False)
@cython.cdivision(True)
cdef double[:] nrtlaux(double [:] X, double [:,::1] G, double [:,::1] tau, int nc):
cdef int i, j, k
cdef double A, SumA, SumB, SumC, SumD, SumE, aux1, aux2
cdef double [:] lngama = np.zeros(nc)
for i in range(nc):
SumC = SumD = SumE = 0.
for j in range(nc):
A = X[j]*G[i,j]
SumA = SumB = 0.
for k in range(nc):
aux1 = X[k]*G[k,j]
SumA += aux1
SumB += aux1*tau[k,j]
SumC += A/SumA*(tau[i,j]-SumB/SumA)
aux2 = X[j]*G[j,i]
SumD += aux2*tau[j,i]
SumE += aux2
lngama[i] = SumD/SumE+SumC
return lngama
def NRTL(np.ndarray[double, ndim=1] X, double T, np.ndarray[double, ndim=2] g,
np.ndarray[double, ndim=2] alpha, np.ndarray[double, ndim=2] g1):
cdef int nc = len(X)
cdef:
double[:,::1] tau = (g/T + g1)
double[:,::1] G = np.exp( -alpha * tau )
lngama = nrtlaux(X, G, tau, nc)
return np.asarray(lngama)
Я использую следующие параметры для оценки функции:
X = np.array([0.5,0.4,0.1])
g = np.array([[0,35.00002657,463.719316],[341.00001923,0,96.02154497],[1194.42262, 534.77089478,0]])
alpha = np.array([[0,0.3456916919878884,0.242020522],[0.3456916919878884,0,0.54 ],[0.242020522,0.54 ,0]])
g1 = np.zeros_like(g)
T = 350.
И я получил следующие результаты:
%timeit NRTL(X,T,g,alpha, g1) #cython
13.9 µs ± 489 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit nrtltp(X,T,g,alpha, g1) #numba
1.82 µs ± 35 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Я немного удивленхорошие результаты от функции joted, также я новичок в Cython, так что я надеялся на какие-либо предложения по улучшению производительности?