Operations in MLX are lazy. Arrays are only computed when needed.
You can force evaluation using eval():
c = a + b # Not evaluated yetmx.eval(c) # Now evaluated
Arrays are automatically evaluated when you:
Print them
Access scalar values with .item()
Convert to NumPy arrays
c = a + bprint(c) # Automatically evaluates# array([2, 4, 6, 8], dtype=float32)# Convert to NumPyimport numpy as npnp_array = np.array(c) # Also evaluates
Compute both function value and gradient efficiently:
import mlx.core as mxdef loss_fn(x): return mx.sum(x ** 2)x = mx.array([1.0, 2.0, 3.0])# Get both value and gradientvalue, grad = mx.value_and_grad(loss_fn)(x)print(value) # 14.0print(grad) # [2.0, 4.0, 6.0]
Operations can run on CPU or GPU without copying data:
import mlx.core as mx# Arrays live in unified memorya = mx.array([1, 2, 3])# Run on GPUb = mx.exp(a, stream=mx.gpu)# Run on CPUc = mx.sin(a, stream=mx.cpu)# No data transfer needed - unified memory!