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

[BUG] LAPACK info is not negative #1794

Open
NAThompson opened this issue Jan 25, 2025 · 1 comment
Open

[BUG] LAPACK info is not negative #1794

NAThompson opened this issue Jan 25, 2025 · 1 comment

Comments

@NAThompson
Copy link
Contributor

NAThompson commented Jan 25, 2025

Describe the bug

When a non-positive semidefinite matrix is passed into the Cholesky decomposition, the info is 2, not a negative number.

To Reproduce

Apply the following patchfile:

diff --git a/mlx/backend/common/cholesky.cpp b/mlx/backend/common/cholesky.cpp
index 62807e6..3f4beeb 100644
--- a/mlx/backend/common/cholesky.cpp
+++ b/mlx/backend/common/cholesky.cpp
@@ -5,6 +5,7 @@
 #include "mlx/backend/common/lapack.h"
 #include "mlx/linalg.h"
 #include "mlx/primitives.h"
+#include <iostream>

 namespace mlx::core {

@@ -51,6 +52,8 @@ void cholesky_impl(const array& a, array& factor, bool upper) {
       throw std::runtime_error(msg.str());
     }

+    std::cout << "Cholesky info = " << info << std::endl;
+
     // Zero out the upper/lower triangle while advancing the pointer to the
     // next matrix at the same time.
     for (int row = 0; row < N; row++) {

And run this code:

#!/usr/bin/env python3

import mlx
import mlx.core

A = mlx.core.array([[1.0, 2.0], [2.0, 1.0]])
print(f"Input A = {A}")
L = mlx.core.linalg.cholesky(A, stream=mlx.core.cpu)
print(f"L={L}")

A_recovered = L@L.T
print(f"L@L^T = {A_recovered}")

Info = 2 will be printed.

Expected behavior

The comment mlx/backend/common/cholesky.cpp in cholesky_impl (confusingly) claim it does not and should not throw, but then it explicitly throws on info < 0:

    // TODO: We do nothing when the matrix is not positive semi-definite
    // because throwing an error would result in a crash. If we figure out how
    // to catch errors from the implementation we should throw.
    if (info < 0) {
      std::stringstream msg;
      msg << "[cholesky] Cholesky decomposition failed with error code "
          << info;
      throw std::runtime_error(msg.str());
    }

However, this condition is never satisfied, as error states are communicated with positive integers. Hence the desired fix is not quite obvious-should the error check condition be fixed and the throw be maintained?

@angeloskath
Copy link
Member

As the comment above if (info < 0) there was a decision made to ignore the case where the matrix is not positive semi-definite because the only other option is to crash the program unfortunately.

In the case of info < 0 then it was an actual runtime error so it makes a bit of sense to crash.

You can also see the discussion at #1743 for more details.

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

No branches or pull requests

2 participants