Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a np.einsum faster when inputs are many identical arrays? (Or any other faster method)

I have a piece of code of type:

nnt = np.real(np.einsum('xa,xb,yc,yd,abcde->exy',evec,evec,evec,evec,quartic))

where evec is (say) an L x L np.float32 array, and quartic is a L x L x L x L x T np.complex64 array.

I found that this routine is rather slow.

I thought that since all the evec's are identical, there might be a faster way of doing this?

Thanks in advance.

like image 935
semmo Avatar asked Jul 09 '20 03:07

semmo


People also ask

What is einsum in NumPy?

The einsum function is one of NumPy's jewels. It can often outperform familiar array functions in terms of speed and memory efficiency, thanks to its expressive power and smart loops.

Why use einsum instead of multiply in NumPy?

Then there’s a good chance einsum will help us do this much faster and more memory-efficiently that combinations of the NumPy functions multiply, sum and transpose would allow. As a small example of the function’s power, here are two arrays that we want to multiply element-wise and then sum along axis 1 (the rows of the array):

What is the difference between NP einsum () and NP JK ()?

Additionally, np.einsum ('ij,jk', a, b) returns a matrix multiplication, while, np.einsum ('ij,jh', a, b) returns the transpose of the multiplication since subscript ‘h’ precedes subscript ‘i’. In explicit mode the output can be directly controlled by specifying output subscript labels.

How does einsum work for 3D arrays?

You’d be forgiven for thinking that for a 3D array, np.einsum ('kij', M) moves the last axis to the first position and shifts the first two axes along. Actually, einsum creates its own output labelling by rearranging labels in alphabetical order. Therefore 'kij' becomes 'kij->ijk' and we have a sort of inverse permutation instead.

Is the einsum function slow?

The tensordot function is also worth comparing for speed. If you search around, you’ll find examples of posts highlighting cases where einsum appears to be slow, especially when operating on several input arrays (such as this GitHub issue ). The einsum function was written by Mark Wiebe.


1 Answers

For start you can reuse the first calculation:

evec2 = np.real(np.einsum('xa,xb->xab',evec,evec))
nnt = np.real(np.einsum('xab,ycd,abcde->exy',evec2,evec2,quartic))

And if you don't care about memory and only need performance:

evec2 = np.real(np.einsum('xa,xb->xab',evec,evec))
nnt = np.real(np.einsum('xab,ycd,abcde->exy',evec2,evec2,quartic,optimize=True))
like image 113
Ehsan Avatar answered Oct 25 '22 01:10

Ehsan