2013-06-06 2 views
4

3D 배열의 각 2D 슬라이스에 기능이 작동했습니다. 성능을 향상시키기 위해 루프를 피하기 위해 함수를 벡터화하는 방법은 무엇입니까? 예를 들어 :ndarray의 하위 배열에서 작동하는 함수를 벡터화

def interp_2d(x0,y0,z0,x1,y1): 
    # x0, y0 and z0 are 2D array 
    # x1 and y1 are 2D array 
    # peform 2D interpolation 
    return z1 

# now I want to call the interp_2d for each 2D slice of z0_3d as following: 
for k in range(z0_3d.shape[2]): 
    z1_3d[:,:,k]=interp_2d(x0, y0, z0_3d[:,:,k], x1, y1) 
+1

의 요인'무엇을 할 interp_2d' 않는에게 이상 잘의 최대 속도를 기대 : 여기

정말 사소한 1D 보간 예입니다? 이 정보가 없으면 벡터화가 가능한지 여부를 알 수있는 방법이 없습니다. 완전히 일반적인 파이썬 함수를 적용하기 위해, 당신이하고있는 방식은 다른 옵션들보다 크게 느려지지 않을 것입니다. "벡터 라이 제이션"은 보통 numpy.vectorize와 같은 래퍼를 적용하는 대신 numpy 함수/표현식을 사용하여 연산을 다시 작성하는 것을 의미합니다. (당연히 다소 혼란 스럽네요 ...) –

+1

'interp_2d'가 단지 쌍 선형, 3 차 또는 가장 가까운 보간이면'scipy.ndimage.map_coordinates' 또는'scipy.ndimage.zoom'을 사용할 수 있습니다. 'x0, y0'과'x1, y'의 관계에 따라 (둘 다 규칙적인 격자 상입니까, 아니면 단지'z0'입니까?). –

+0

Joe, 답장을 보내 주셔서 감사합니다. interp_2d의 구현을 고려할 필요가 없습니다. 범위에서 k에 대한 을 (z0_3d.shape [2]) : 난 그냥 다음 코드를 벡터화 할 수있는 방법이 있는지 알고 싶어 z1_3d의 [: : K] = interp_2d (X0, Y0, z0_3d의 [:, :, k], x1, y1) –

답변

1

이는 interp_2d를 다시 구현하지 않고 벡터화 할 수 없습니다. 그러나 interp_2d을 보간 유형이라고 가정하면 조작은 선형입니다. 즉, lambda z0: interp_2d(x0, y0, z0, x1, y1)np.dot(M, z0)과 같습니다. Mx0, y0, x1y1에 의존하는 일부 (아마 드문 드문) 매트릭스입니다. 지금은 interp_2d 함수를 호출하여 매번 동일한 경우에도 모든 호출에서이 행렬을 암시 적으로 다시 계산합니다. 그 행렬이 한 번 무엇인지 알아 내서 새로운 z0에 여러 번 다시 적용하는 것이 더 효율적입니다. n이 매우 큰

x0 = [0., 1.] 
x1 = 0.3 
z0_2d = "some very long array with shape=(2, n)" 

def interp_1d(x0, z0, x1): 
    """x0 and z0 are length 2, 1D arrays, x1 is a float between x0[0] and x0[1].""" 

    delta_x = x0[1] - x0[0] 
    w0 = (x1 - x0[0])/delta_x 
    w1 = (x0[1] - x1)/delta_x 
    return w0 * z0[0] + w1 * z0[1] 

# The slow way. 
for i in range(n): 
    z1_2d[i] = interp_1d(x0, z0_2d[:,i], x1) 
# Notice that the intermediate products w1 and w2 are the same on each 
# iteration but we recalculate them anyway. 

# The fast way. 
def interp_1d_weights(x0, x1): 
    delta_x = x0[1] - x0[0] 
    w0 = (x1 - x0[0])/delta_x 
    w1 = (x0[1] - x1)/delta_x 
    return w0, w1 

w0, w1 = interp_1d_weights(x0, x1) 
z1_2d = w0 * z0_2d[0,:] + w1 * z0_2d[1:0] 

경우, 100

관련 문제