簡體   English   中英

我如何加快python嵌套循環的速度?

[英]How do i speed up a python nested loop?

我正在嘗試通過計算身體每一側的效果來計算掩埋物體的重力效果,然后將其總和累加起來,以便在一個測站上進行一次測量,並重復多個測站。 代碼如下(主體是一個正方形,代碼圍繞它按順時針方向進行計算,這就是為什么它從-x返回到-x坐標的原因)

grav = []
x=si.arange(-30.0,30.0,0.5)

#-9.79742526     9.78716693    22.32153704    27.07382349  2138.27146193
xcorn = (-9.79742526,9.78716693 ,9.78716693 ,-9.79742526,-9.79742526)
zcorn = (22.32153704,22.32153704,27.07382349,27.07382349,22.32153704)
gamma = (6.672*(10**-11))#'N m^2 / Kg^2'
rho = 2138.27146193#'Kg / m^3'
grav = []
iter_time=[]
def procedure():
    for i in si.arange(len(x)):# cycles position
        t0=time.clock()
        sum_lines = 0.0

        for n in si.arange(len(xcorn)-1):#cycles corners
            x1 = xcorn[n]-x[i]
            x2 = xcorn[n+1]-x[i]
            z1 = zcorn[n]-0.0  #just depth to corner since all observations are on the surface.
            z2 = zcorn[n+1]-0.0
            r1 = ((z1**2) + (x1**2))**0.5
            r2 = ((z2**2) + (x2**2))**0.5 
            O1 = si.arctan2(z1,x1)
            O2 = si.arctan2(z2,x2)
            denom = z2-z1
            if denom == 0.0:
                denom = 1.0e-6

            alpha = (x2-x1)/denom

            beta = ((x1*z2)-(x2*z1))/denom
            factor = (beta/(1.0+(alpha**2)))
            term1 = si.log(r2/r1)#log base 10
            term2 = alpha*(O2-O1)
            sum_lines = sum_lines + (factor*(term1-term2))
        sum_lines = sum_lines*2*gamma*rho
        grav.append(sum_lines)
        t1 = time.clock()
        dt = t1-t0
        iter_time.append(dt)

感謝您對加快此循環速度的任何幫助。

您的xcorn和zcorn值會重復,因此請考慮緩存某些計算的結果。

查看timeit和profile模塊,以獲取有關花費最多計算時間的更多信息。

在Python循環中訪問numpy數組的各個元素的效率非常低。 例如,以下Python循環:

for i in xrange(0, len(a), 2):
    a[i] = i

會比以下慢得多:

a[::2] = np.arange(0, len(a), 2)

您可以使用更好的算法(較少的時間復雜性)或對numpy數組使用矢量運算,如上例所示。 但是更快的方法可能只是使用Cython編譯代碼:

#cython: boundscheck=False, wraparound=False
#procedure_module.pyx
import numpy as np
cimport numpy as np

ctypedef np.float64_t dtype_t

def procedure(np.ndarray[dtype_t,ndim=1] x, 
              np.ndarray[dtype_t,ndim=1] xcorn):
    cdef:
        Py_ssize_t i, j
        dtype_t x1, x2, z1, z2, r1, r2, O1, O2 
        np.ndarray[dtype_t,ndim=1] grav = np.empty_like(x)
    for i in range(x.shape[0]):
        for j in range(xcorn.shape[0]-1):
            x1 = xcorn[j]-x[i]
            x2 = xcorn[j+1]-x[i]
            ...
        grav[i] = ...
    return grav

不必定義所有類型,但是與Python相比,如果需要顯着提高速度,則至少應定義數組和循環索引的類型。

您可以使用cProfile (Cython支持它)來代替手動調用time.clock()

調用procedure()

#!/usr/bin/env python
import pyximport; pyximport.install() # pip install cython
import numpy as np

from procedure_module import procedure

x = np.arange(-30.0,30.0,0.5)
xcorn = np.array((-9.79742526,9.78716693 ,9.78716693 ,-9.79742526,-9.79742526))
grav = procedure(x, xcorn)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM