3

I have a 3-Dimensional numpy array A. I would like to multiply every element A[i,j,k] by w*( i / Lx + j / Ly + k / Lz ) where w, Lx, Ly and Lz are real numbers (floats). Performing this operation in a for loop is highly impractical, since I need to be able to scale this for large arrays and a for loop over the three indices ijk scales in O(N^3).

Is there an efficient way to perform an operation on each element of a numpy array that cares about index?

1
  • Create 3 3D numpy array: I is like I[i,:,:]=i, J is like J[:,j,:]=j and K[:,:,k]=k. Then A*w*(I/Lx + J/Ly + K/Lz) Commented Oct 13, 2015 at 9:25

1 Answer 1

6

You can use broadcasting -

M,N,R = A.shape

p1 = np.arange(M)[:,None,None]/Lx
p2 = np.arange(N)[:,None]/Ly
p3 = np.arange(R)/Lz

out = A/(w*(p1 + p2 + p3))

You can also use np.ix_ for a more elegant solution -

M,N,R = A.shape
X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R))
out = A/(w*((X/Lx) + (Y/Ly) + (Z/Lz)))

Runtime tests and output verification -

Function definitions:

def vectorized_app1(A, w, Lx, Ly, Lz ):
    M,N,R = A.shape
    p1 = np.arange(M)[:,None,None]/Lx
    p2 = np.arange(N)[:,None]/Ly
    p3 = np.arange(R)/Lz
    return A/(w*(p1 + p2 + p3))

def vectorized_app2(A, w, Lx, Ly, Lz ):
    M,N,R = A.shape
    X,Y,Z = np.ix_(np.arange(M),np.arange(N),np.arange(R))
    return A/(w*((X/Lx) + (Y/Ly) + (Z/Lz)))

def original_app(A, w, Lx, Ly, Lz ):
    out = np.empty_like(A)
    M,N,R = A.shape
    for i in range(M):
        for j in range(N):
            for k in range(R):
                out[i,j,k] = A[i,j,k]/(w*( (i / Lx) + (j / Ly) + (k / Lz) ))
    return out

Timings:

In [197]: # Inputs
     ...: A = np.random.rand(100,100,100)
     ...: w, Lx, Ly, Lz = 2.3, 3.2, 4.2, 5.2
     ...: 

In [198]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app1(A,w,Lx,Ly,Lz))
Out[198]: True

In [199]: np.allclose(original_app(A,w,Lx,Ly,Lz),vectorized_app2(A,w,Lx,Ly,Lz))
Out[199]: True

In [200]: %timeit original_app(A, w, Lx, Ly, Lz )
1 loops, best of 3: 1.39 s per loop

In [201]: %timeit vectorized_app1(A, w, Lx, Ly, Lz )
10 loops, best of 3: 24.6 ms per loop

In [202]: %timeit vectorized_app2(A, w, Lx, Ly, Lz )
10 loops, best of 3: 24.2 ms per loop
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.