我使用python和numpy用显式有限差分法(FDM)求解扩散方程。效率问题发生在for循环期间解决方程式,我找不到用numpy进行矢量化的方法。我用Google搜索,发现cython是其中一个解决方案。以下问题与cython和cython并行有关。
如果我希望代码更高效,我该怎么办?我尝试了cython并行,但是因为for循环中的代码不是纯粹的c类型,可能会出现gil问题。
我的代码看起来像吼叫:
import numpy as np
cimport numpy as np
cimport cython
import cython
from cython.parallel import prange, parallel
DTYPEFLOAT = np.float32
DTYPEINT8 = np.int8
DTYPEDOUBLE = np.double
ctypedef np.float32_t DTYPE_t
ctypedef np.double_t DTYPEDOUBLE_t
ctypedef np.int8_t DTYPEINT8_t
@cython.boundscheck(False)
@cython.wraparound(False)
cdef int[:, :] _MooreNeighborhood(int iN, int jN, int i0, int j0):
cdef int[:,:] mOutput
cdef unsigned int iU, iD, jL, jR
mOutput = np.empty((8,2), dtype=np.int32)
if i0 == 0:
iD = iN-1
else:
iD = i0-1
if i0 == iN-1:
iU = 0
else:
iU = i0+1
if j0 == 0:
jL = jN-1
else:
jL = j0-1
if j0 == jN-1:
jR = 0
else:
jR = j0+1
mOutput[0,0] = iD
mOutput[0,1] = j0
mOutput[1,0] = i0
mOutput[1,1] = jR
mOutput[2,0] = iU
mOutput[2,1] = j0
mOutput[3,0] = i0
mOutput[3,1] = jL
mOutput[4,0] = iD
mOutput[4,1] = jR
mOutput[5,0] = iU
mOutput[5,1] = jR
mOutput[6,0] = iU
mOutput[6,1] = jL
mOutput[7,0] = iD
mOutput[7,1] = jL
return mOutput
cpdef np.ndarray[DTYPEDOUBLE_t, ndim=2] _diffusionFD2(np.ndarray[DTYPEDOUBLE_t, ndim=2] mInput, np.ndarray[DTYPEINT8_t, ndim=2] mRegion,
double coeff_D, double delta_i, double delta_j, double delta_t):
cdef unsigned int iN, jN, i, j, iR, jR, iL, jL, iU, jU, iD, jD
cdef double cR, cL, cU, cD, cC
cdef np.ndarray[DTYPEDOUBLE_t, ndim=2] mOutput
cdef int[:, :] neighborhood
if not np.any(mRegion):
return mInput
iN = mInput.shape[0]
jN = mInput.shape[1]
mOutput = np.copy(mInput)
for i in range(iN):
for j in range(jN):
if mRegion[i][j]:
neighborhood = _MooreNeighborhood(iN, jN, i, j)
cC = mInput[i,j]
iR = neighborhood[1,0]
jR = neighborhood[1,1]
iL = neighborhood[3,0]
jL = neighborhood[3,1]
iD = neighborhood[0,0]
jD = neighborhood[0,1]
iU = neighborhood[2,0]
jU = neighborhood[2,1]
if not mRegion[iR,jR]:
cR = cC
else:
cR = mInput[iR,jR]
if not mRegion[iL,jL]:
cL = cC
else:
cL = mInput[iL,jL]
if not mRegion[iU,jU]:
cU = cC
else:
cU = mInput[iU,jU]
if not mRegion[iD,jD]:
cD = cC
else:
cD = mInput[iD,jD]
mOutput[i,j] = cC+coeff_D*delta_t*((cU + cD - 2*cC)/(delta_i**2) + (cR + cL - 2*cC)/(delta_j**2))
return mOutput
#