Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inverse of large matrices (ILP64?) #14780

Open
pmgurman opened this issue Sep 28, 2021 · 4 comments
Open

Inverse of large matrices (ILP64?) #14780

pmgurman opened this issue Sep 28, 2021 · 4 comments

Comments

@pmgurman
Copy link

Hi All,

I have an odd problem and I don't know if this is the correct place to ask, so apologies if not but here goes...

Some of the matrices that I have to invert are >50k per axis (i.e. 50k x 50k) and symmetric. The naive approach is np.linalg.inv(), but this means storing the square matrix. I know that LAPACK has inversion algorithms that work on the one triangle only, but once I exceed the limit of 32 bit integers to address, they crash (n (n+1) / 2 > 2^32-?). Here is some sample code and a crash message:

      1 def invp(B):
----> 2     Bp = sp.linalg.lapack.dtrttf(B)[0]
      3     Bpc = sp.linalg.lapack.dpftrf(B.shape[0], Bp)[0]
      4     Bpi = sp.linalg.lapack.dpftri(B.shape[0], Bpc)[0]
      5     Bi = sp.linalg.lapack.dtfttr(B.shape[0], Bpi)[0]

ValueError: failed to create intent(cache|hide)|optional array-- must have defined 
dimensions but got (-897458648,) 

I believe this is due to my scipy not using ILP64 but I don't know. I am using Anaconda and Scipy version 1.6.2.

This might help, if i try to force ILP64, I get the following.

sp.linalg.get_lapack_funcs('trttf', (B,), ilp64=True)

RuntimeError: LAPACK ILP64 routine requested, but Scipy compiled only with 32-bit BLAS

Note, I understand that it is best to avoid matrix inversion, however, the need still arises. Given the size of the matrices I am working with here, almost having the memory usage would help :). Any help or guidance as to where to seek answers is greatly appreciated.

@mdhaber
Copy link
Contributor

mdhaber commented Sep 28, 2021

Are you able to say what you want to do with the inverse? I've wanted to compile a list of reasonable uses of numerical matrix inverses.

@pmgurman
Copy link
Author

In my case, the calculation can be written as (AA' + B)^-1 + C, with this result then added into a sub-block of another matrix. In my case, B and C are symmetric so I wanted to try to utilise the rectangular full packed format functions in LAPACK to reduce memory usage, but it seems to crash when the matrix requires 64 integers to address, which is why I was mentioning ILP64. Maybe the title is misleading?

@mdhaber, I agree with you that there are reasonable reasons to invert matrices explicitly, which mostly revolve around the need to do more complex calculations with the results of an inverse. While you could use, say, scipy.linalg.solve with columns of the identity matrix to calculate through clockwise columns, this would get messy for something like A^-1 A^-1.

@mdhaber
Copy link
Contributor

mdhaber commented Sep 29, 2021

Thanks!

i agree with you that there are reasonable reasons to invert matrices

Oh, i don't know firsthand or have my own opinion. I just always remember reading or hearing that it is almost never a good idea to invert, but those sources would never give examples of the exceptions to that rule.

Not sure that i can help here. @ilayn maybe?

@ilayn
Copy link
Member

ilayn commented Sep 29, 2021

First the technical part, the standard build of SciPy if I am not mistaken is built with ILP64 disabled. Hence you need to use a BLAS implementation that uses ILP64. OpenBLAS can be built to use 64-bit integers with the INTERFACE64=1 flag. And in conda I think MKL has a similar flag. Then you can build SciPy with it and that error will disappear. You can then use the 64bit interface.

However even then, matrix inversion would be, I am guessing, useless since at these sizes the entries wildly swing due to numerical error build-up. You can let LAPACK do the hardwork with dsytri computing the inverse directly, it won't help with the precision but at least you don't need to shift LU representation around.

Instead as Matt said, you can avoid almost always the explicit inverses. But if you really have to, one obvious way is of course Schur complement which the typical matrix inversion lemma applies https://en.wikipedia.org/wiki/Schur_complement The idea is to reduce the size of the blocks that are inverted and carry out explicit expressions. But you have to somehow make sure that some inverse of the subblock exists

Another case is when B + AA' is pos def you can (and should) dpotri instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants