Skip to content
C.W.K.
Stream
Lesson 06 of 06 · published

Honest Assessment — What MLX Is Not, As of Today

~16 min · honest, limits, linalg-gap

Level 0Curious
0 XP0/51 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

The unflinching list

This quest has spent five tracks selling MLX. This lesson is the calibrating opposite — what MLX is not good at, what's missing, what's still rough as of 2026-05, with the version-sensitive items (the linear-algebra list, JACCL's macOS floor) re-checked on 2026-09-15. Use it to set realistic expectations and to know which limitations are likely to close versus which are structural.

The linalg gap

MLX's mx.linalg module is much smaller than NumPy's or PyTorch's. Notable absences as of mlx 0.32.x include:

  • lstsq — least-squares solver. Workaround via pinv (the code block below) or solve on the normal equations.
  • matrix_rank, matrix_exp, cond — convenience functions you'd use for numerical analysis. Not in MLX core.
  • The basic decompositions (cholesky, qr, svd, lu, eig) are in MLX, and since 0.32.0 so are det and slogdet. The bones are there; much of the convenience layer isn't yet, and it is filling in.

If your work involves heavy linear algebra beyond ML training, MLX may not be enough. NumPy + your CPU may be the right tool for that part of the pipeline.

Documentation that lags the codebase

MLX's docs are accurate but incomplete. The official docs at ml-explore.github.io/mlx/ cover most APIs but lag behind the latest releases by weeks to months. For frontier features, the truth is in the source code (mlx-lm's GitHub repo) and the release notes — not the docs.

Distributed training that's still early

JACCL (covered briefly in prod.lesson6) is the active research area for MLX distributed training across Thunderbolt-connected Macs. As of 2026-05 it needs macOS 26.2 or later and is not yet drop-in for the PyTorch distributed-training stack. If you're training across multiple machines today, PyTorch + DeepSpeed on NVIDIA is still the practical answer.

CUDA backend that's incomplete

Since v0.27, mlx has a CUDA backend on Linux for cross-platform inference. As of 2026-05 it's functional but behind the Apple Silicon path on coverage and performance. Use it when you need MLX-shaped code to run somewhere other than Mac, but don't expect parity with the native Apple Silicon experience.

Smaller library ecosystem than PyTorch

The PyTorch ecosystem has thousands of third-party libraries — vision, audio, RL, robotics, scientific computing — that simply don't exist for MLX. Some of the gaps are filled by MLX-native packages (mlx-vlm, mlx-audio); others require you to use NumPy/PyTorch alongside MLX in a hybrid pipeline.

What MLX is, despite all this

The right summary is: MLX is the best framework for serving and fine-tuning LLMs on Apple Silicon, and a credible framework for general ML research on Apple Silicon. It is not yet the right framework for heavy numerical analysis, multi-machine distributed training, or use cases that depend on the long tail of PyTorch ecosystem libraries. Knowing where the line is means you reach for MLX where it's strong and reach for something else where it isn't — without confused expectations either way.

A least-squares workaround that holds up

The code block below fits a line through four points with mx.linalg.pinv, then checks the answer against np.linalg.lstsq. Two details are worth copying. MLX does not yet run pinv or det on the GPU — the error message says so and tells you to pass a CPU stream — so the block passes stream=mx.cpu. And the NumPy comparison is the point, not decoration: a workaround you haven't checked against a reference implementation is one more hypothesis.

Code

Workaround for the missing lstsq·python
# mx.linalg.lstsq doesn't exist in mlx 0.32.x (det and slogdet arrived in 0.32.0).
# Least squares via the pseudoinverse: x = pinv(A) @ b minimizes ||Ax - b||.
import mlx.core as mx
import numpy as np

# Fit y = c0 + c1 * t through four points
A = mx.array([[1.0, 1.0], [1.0, 2.0], [1.0, 3.0], [1.0, 4.0]])
b = mx.array([6.0, 5.0, 7.0, 10.0])

# pinv and det are not yet supported on the GPU in MLX: pass a CPU stream
x = mx.linalg.pinv(A, stream=mx.cpu) @ b
print("mlx   :", x)

# Cross-check against NumPy's reference implementation
x_np, *_ = np.linalg.lstsq(np.array(A), np.array(b), rcond=None)
print("numpy :", x_np)

# And det is no longer a workaround at all
print("det   :", mx.linalg.det(mx.array([[4.0, 2.0], [3.0, 1.0]]), stream=mx.cpu))

# Verified output (2026-09-15, mlx 0.32.2):
#   mlx   : array([3.5, 1.4], dtype=float32)
#   numpy : [3.5 1.4]
#   det   : array(-2, dtype=float32)

External links

Exercise

Identify a numerical-analysis workflow you've done before — anything involving determinants, least-squares, eigenvalues for non-symmetric matrices, etc. Look up which of the building blocks exist in MLX vs which require workarounds. For your specific workflow, would you use MLX, NumPy, or a hybrid? Two sentences explaining your choice.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.