Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NumPy tensordot MemoryError

I have two matrices -- A is 3033x3033, and X is 3033x20. I am running the following lines (as suggested in the answer to another question I asked):

n, d = X.shape
c = X.reshape(n, -1, d) - X.reshape(-1, n, d)
return np.tensordot(A.reshape(n, n, -1) * c, c, axes=[(0,1),(0,1)])

On the final line, Python simply stops and says "MemoryError". How can I get around this, either by changing some setting in Python or performing this operation in a more memory-efficient way?

like image 387
Andrew Latham Avatar asked Feb 22 '26 16:02

Andrew Latham


2 Answers

Here is a function that does the calculation without any for loops and without any large temporary array. See the related question for a longer answer, complete with a test script.

def fbest(A, X):
  ""
  KA_best = np.tensordot(A.sum(1)[:,None] * X, X, axes=[(0,), (0,)])
  KA_best += np.tensordot(A.sum(0)[:,None] * X, X, axes=[(0,), (0,)])
  KA_best -= np.tensordot(np.dot(A, X), X, axes=[(0,), (0,)])
  KA_best -= np.tensordot(X, np.dot(A, X), axes=[(0,), (0,)])
  return KA_best

I profiled the code with your size arrays: enter image description here

I love sp.einsum by the way. It is a great place to start when speeding up array operations by removing for loops. You can do SOOOO much with one call to sp.einsum.

The advantage of np.tensordot is that it links to whatever fast numerical library you have installed (i.e. MKL). So, tensordot will run faster and in parallel when you have the right libraries installed.

like image 175
Will Martin Avatar answered Feb 26 '26 04:02

Will Martin


If you replace the final line with

return np.einsum('ij,ijk,ijl->kl',A,c,c)

you avoid creating the A.reshape(n, n, -1) * c (3301 by 3301 by 20) intermediate that I think is your main problem.

My impression is that the version I give is probably slower (for cases where it doesn't run out of memory), but I haven't rigourously timed it.

It's possible you could go further and avoid creating c, but I can't immediately see how to do it. It'd be a case of following writing the whole thing in terms of sums of matrix indicies and seeing what it simplified to.

like image 27
DavidW Avatar answered Feb 26 '26 05:02

DavidW