Skip to content

[Feature] Metal implementation of linalg APIs #1392

Open

Description

@vgoklani

Describe the bug
The mx.linalg.svd crashes

To Reproduce

Include code snippet

import mlx.core as mx

a = mx.array([ [1., 2], [2, 3] ])

u, singular_values, v_transpose = mx.linalg.svd(a=a)

libc++abi: terminating due to uncaught exception of type std::runtime_error: [SVD::eval_gpu] Metal SVD NYI.

Expected behavior

import numpy as np
import mlx.core as mx

a = mx.array([ [1., 2], [2, 3] ])

u, singular_values, v = np.linalg.svd(a=a)

singular_values
array([4.236068 , 0.23606798], dtype=float32)

Desktop (please complete the following information):
MLX 0.17.2

Additional context
Add any other context about the problem here.

Activity

  1. awni commented on Sep 3, 2024

    @awni
    Member

    That is unfortunately expected behavior. Right now svd (and several other linalg operations are only supported on the CPU back-end. You can fix that by passing in the CPU stream to the operation like so:

    import mlx.core as mx
    
    a = mx.array([ [1., 2], [2, 3] ])
    
    u, singular_values, v_transpose = mx.linalg.svd(a=a, stream=mx.cpu)
    
  2. awni commented on Sep 3, 2024

    @awni
    Member

    I'm going to change this from a bug to a feature request and mark it as such. Note it's not a trivial op to implement on the GPU so it could take some time to get this feature into MLX.

  3. changed the title [-][BUG] SVD crashes[/-] [+][Feature] Metal implementation of SVD[/+] on Sep 3, 2024
  4. vgoklani commented on Sep 3, 2024

    @vgoklani
    Author

    Thanks!

  5. ArkAung commented on Oct 7, 2024

    @ArkAung

    Is anyone working on this? If not, I would like to start working on this. Happy to collaborate with other contributors who would like to collab on the PR.

  6. awni commented on Oct 8, 2024

    @awni
    Member

    I don't know of anyone working on this. Happy to accept a contribution.

  7. huangrzh commented on Dec 4, 2024

    @huangrzh

    Is anyone working on this? If not, I would like to start working on this. Happy to collaborate with other contributors who would like to collab on the PR.

    Hi, how is it going with SVD?

  8. hehua2008 commented on Jan 11, 2025

    @hehua2008

    Any progress? mx.cpu is too slow!😂

  9. intproduct commented on Nov 2, 2025

    @intproduct

    Hello, I'd like to ask if there has been any progress on the GPU SVD feature?

  10. awni commented on Nov 5, 2025

    @awni
    Member

    No progress :\

  11. ArkAung commented on Nov 15, 2025

    @ArkAung

    I was working on it for a while and got side-tracked because of other responsibilities. If people want this, I will properly dedicate this and revive the draft PR (now stale and closed). There are some challenges with making it work for large matrices. I am willing to take co-contributors to get this across the line.

  12. changed the title [-][Feature] Metal implementation of SVD[/-] [+][Feature] Metal implementation of linalg APIs[/+] on Mar 18, 2026
  13. sashko-zakharchuk commented on Aug 11, 2026

    @sashko-zakharchuk
    Contributor

    Unless someone's already on the CUDA side of this, I'll start with a Cholesky PR (#1026)
    backed by cuSOLVER, with inverse as a follow-up. Following the #3825 discussion: a vendor
    library call with cached handles like the cuDNN path in the CUDA backend, no new hand-written
    kernels (I saw where #3851 went), and no shape-based CPU dispatch; small matrices can keep
    using the CPU stream. I'd benchmark where cuSOLVER starts winning on sm_120. Leaving SVD out
    of scope for now.

  14. ternaus commented on Aug 22, 2026

    @ternaus
    Contributor

    Generic Metal linalg.inv investigation

    I implemented a generic float32 Metal prototype for mx.linalg.inv in #4375. It uses MPSMatrixDecompositionLU followed by MPSMatrixSolveLU against identity. The PR remains a draft because the performance results require a backend-dispatch decision before this route is suitable for merging.

    On an M4 Max (16-core CPU), macOS 26.4.1, these are medians of 20 runs after 5 warm-ups. Equivalent inputs were materialized on CPU or Metal before timing; host-device copies are excluded. Each timed run includes inv, eval, and synchronize.

    Matrix shape CPU (ms) Metal (ms) CPU / Metal
    64x64 0.048 0.925 0.05x
    256x256 0.186 3.438 0.05x
    1024x1024 5.250 15.509 0.34x
    2048x2048 27.548 29.765 0.93x
    4096x4096 180.299 79.006 2.28x

    Command-buffer profiling shows that this is not primarily MLX handoff overhead. For 1024x1024, MPS itself occupies 14.0–14.6 ms of a 15.7 ms end-to-end Metal operation, while CPU takes about 5.2 ms. For a 32x64x64 batch, the MPS work takes about 21 ms and per-matrix host encoding adds about 2.1 ms; CPU takes about 0.7 ms.

    I also tested native MPS batching outside MLX. This is a likely Apple MPS framework bug, not a MLX bug: a standalone program constructs two matrices with matrices=2, sets batchSize=2 on both LU and solve operations, and runs with Metal API Validation enabled. It produces the correct inverse for batch 0 and zeros for batch 1, without a validation error. MLX therefore keeps the correct per-matrix encoding loop; the native MPS batch route is not safe to use. The repro needs escalation to Apple MPS engineering.

    The current benchmark and reproduction command are in #4375. The remaining design question is a generic dispatch policy for small and medium matrices versus a new custom Metal backend.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions