与Fortran相比,Numpy计算速度太慢

2024-09-28 21:35:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我过去主要使用Fortran,但最近我开始使用python和Numpy进行深度学习应用

但是,在python中计算double for循环要比Fortran慢得多。我已经知道Fortran最初的计算速度很快,但我想知道我的python代码是否有任何错误。以下是我使用的代码:

for it in range(nt):
    if it%20 == 1:
        print(it,'//',nt)

    itimenum4 = "%.4i" %(it)
    
    ppsix2[:,:]=0.; ppsiz2[:,:]=0.
    apsix2[:,:]=0.; apsiz2[:,:]=0.
    ax[:,:]=0.; az[:,:]=0.
    p3[:,:]=0.
    
    for iz in range(2,nnz+1):
        for ix in range(2,nnx+1):

            pdx2=(p2[ix+1,iz]-p2[ix,iz])*a1+(p2[ix+2,iz]-p2[ix-1,iz])*a2
            pdz2=(p2[ix,iz+1]-p2[ix,iz])*a1+(p2[ix,iz+2]-p2[ix,iz-1])*a2

            dpml0=math.log(1./R)*3.*vp[ix,iz]/(2.*dx*pml)

            if ix <= pml:
                dpml=dpml0*(float(pml-ix+1)/float(pml))**2
                damp=math.exp(-dpml*dt)
                ppsix2[ix,iz]=damp*ppsix1[ix,iz]+(damp-1.)*pdx2

            if ix >nx+pml:
                dpml=dpml0*(float(ix-(nx+pml))/float(pml))**2
                damp=math.exp(-dpml*dt)
                ppsix2[ix,iz]=damp*ppsix1[ix,iz]+(damp-1.)*pdx2

            if iz > nz:
                dpml=dpml0*(float(iz-(nz))/float(pml))**2
                damp=math.exp(-dpml*dt)
                ppsiz2[ix,iz]=damp*ppsiz1[ix,iz]+(damp-1.)*pdz2

            ax[ix,iz]=pdx2+ppsix2[ix,iz]
            az[ix,iz]=pdz2+ppsiz2[ix,iz]
        
    az[:,1]=az[:,2]
    az[:,0]=az[:,3]

    for iz in range(2,nnz+1):
        for ix in range(2,nnx+1):
            adx=a1*(ax[ix,iz]-ax[ix-1,iz])+a2*(ax[ix+1,iz]-ax[ix-2,iz])
            adz=a1*(az[ix,iz]-az[ix,iz-1])+a2*(az[ix,iz+1]-az[ix,iz-2])

            dpml0=math.log(1./R)*3.*vp[ix,iz]/(2.*dx*pml)

            if ix <= pml:
                dpml=dpml0*(float(pml-ix+1)/float(pml))**2
                damp=math.exp(-dpml*dt)
                apsix2[ix,iz]=damp*apsix1[ix,iz]+(damp-1.)*adx

            if ix > nx+pml:
                dpml=dpml0*(float(ix-(nx+pml))/float(pml))**2
                damp=math.exp(-dpml*dt)
                apsix2[ix,iz]=damp*apsix1[ix,iz]+(damp-1.)*adx

            if iz > nz:
                dpml=dpml0*(float(iz-(nz))/float(pml))**2
                damp=math.exp(-dpml*dt)
                apsiz2[ix,iz]=damp*apsiz1[ix,iz]+(damp-1.)*adz

            px2=adx+apsix2[ix,iz]
            pz2=adz+apsiz2[ix,iz]

            p3[ix,iz]=2.*p2[ix,iz]-p1[ix,iz]+(dt*vp[ix,iz])**2*((px2+pz2)+srcf[ix,iz]*source[it])

            if iz == recz:
                mod_p[ix,it]=p3[ix,iz]

    p3[:,0:2]=0.

    p1[:,:]=p2[:,:]
    p2[:,:]=p3[:,:]
    ppsix1[:,:]=ppsix2[:,:]
    ppsiz1[:,:]=ppsiz2[:,:]
    apsix1[:,:]=apsix2[:,:]
    apsiz1[:,:]=apsiz2[:,:]

这是地球物理学中传统的一阶声波方程。不管怎样,我使用了Numpy数组。有没有什么因素使计算速度变慢

谢谢


Tags: forifdtitmathaxfloataz
2条回答

不幸的是,由于python是一种解释语言(与编译的Fortran相比),所以在使用python进行循环时,无法获得类似的速度

有几种方法可以解决这个问题。一种方法是尝试使用numpy数组和numpy数学函数对for循环进行矢量化。通过这样做,您将把代码中计算量大的部分传递给预编译的numpy库

另一种加速python代码的方法是使用库来编译代码。一个这样的库是numba,它提供了即时编译选项

几乎没有一项工作看起来像是矢量化的,例如,它正在做提取单个元素ppsize1[ix,iz]以用于乘法

Numpy并没有像Fortran那样编译成快速的东西,它的快速之处在于它有快速的例程,可以同时对大块数据进行操作。如果不显式地对算法的可矢量化部分进行编码,那么numpy甚至比普通python都要慢

相关问题 更多 >