mlx-go provides Go bindings for Apple's MLX framework, enabling high-performance machine learning on Apple Silicon.
import mx "github.com/guptaaryan16/mlx_go/core"// From Go slices
arr := mx.FromSlice([]float32{1.0, 2.0, 3.0, 4.0})
mat := mx.FromSlice2D([][]float32{{1, 2}, {3, 4}})
// Scalar arrays
scalar := mx.NewArrayFloat32(3.14)
intVal := mx.NewArrayInt(42)
// Creation functions
zeros := mx.Zeros([]int32{3, 3}, mx.Float32)
ones := mx.Ones([]int32{2, 4}, mx.Float32)
eye := mx.Eye(3, 3, 0, mx.Float32) // 3x3 identity matrix
identity := mx.Identity(4, mx.Float32) // 4x4 identity
arange := mx.Arange(0, 10, 1, mx.Float32) // [0, 1, 2, ..., 9]
linspace := mx.Linspace(0, 1, 5, mx.Float32) // [0, 0.25, 0.5, 0.75, 1]arr := mx.FromSlice([]float32{1, 2, 3, 4, 5, 6})
arr = mx.Reshape(arr, []int32{2, 3})
shape := arr.Shape() // []int32{2, 3}
ndim := arr.Ndim() // 2
size := arr.Size() // 6
dtype := arr.Dtype() // mx.Float32
itemSize := arr.ItemSize() // 4 (bytes per element)MLX uses lazy evaluation. Call Eval() to trigger computation:
result := mx.Add(a, b)
result.Eval() // Computation happens here
result.PrintArray()mx.Float32 // 32-bit floating point
mx.Float16 // 16-bit floating point
mx.BFloat16 // Brain floating point
mx.Int32 // 32-bit integer
mx.Int64 // 64-bit integer
mx.Uint32 // Unsigned 32-bit integer
mx.Bool // Boolean// Arithmetic
c := mx.Add(a, b)
c := mx.Subtract(a, b)
c := mx.Multiply(a, b)
c := mx.Divide(a, b)
// Unary operations
abs := mx.Abs(a)
neg := mx.Negative(a)
sqr := mx.Square(a)
sqrt := mx.Sqrt(a)
exp := mx.Exp(a)
log := mx.Log(a)// Matrix multiplication: (m×n) @ (n×p) = (m×p)
C := mx.MatMul(A, B)
// Matrix-matrix multiply-add: C = alpha*A@B + beta*C
result := mx.AddMM(C, A, B, alpha, beta)
// Transpose
aT := mx.Transpose(a)
// Reshape
reshaped := mx.Reshape(a, []int32{4, 4})s := mx.Sum(a)
m := mx.Mean(a)
p := mx.Prod(a)
mn := mx.Min(a)
mx := mx.Max(a)
// Along specific axis
sumAxis := mx.SumAxis(a, 0, false) // Sum along axis 0result := mx.Equal(a, b)
result := mx.NotEqual(a, b)
result := mx.Greater(a, b)
result := mx.GreaterEqual(a, b)
result := mx.Less(a, b)
result := mx.LessEqual(a, b)relu := mx.ReLU(x)
sigmoid := mx.Sigmoid(x)
softmax := mx.Softmax(x, axis)
logSoftmax := mx.LogSoftmax(x, axis)
gelu := mx.GELU(x)
silu := mx.SiLU(x) // Swish activation
leakyRelu := mx.LeakyReLU(x, 0.01)// RMS Normalization (used in LLaMA, etc.)
normed := mx.RMSNorm(x, &weight, eps)
// Layer Normalization
normed := mx.LayerNorm(x, &weight, &bias, eps)// Scaled Dot-Product Attention
output := mx.ScaledDotProductAttention(queries, keys, values, scale, &mask)
// Causal attention (for autoregressive models)
output := mx.ScaledDotProductAttentionCausal(queries, keys, values, scale)// Rotary Position Embedding (RoPE)
output := mx.RoPE(x, dims, traditional, base, scale, offset)
// RoPE with custom frequencies
output := mx.RoPEWithFreqs(x, dims, traditional, scale, offset, freqs)// 1D Convolution
out := mx.Conv1d(input, weight, stride, padding, dilation, groups)
// 2D Convolution
out := mx.Conv2d(input, weight, stride0, stride1, padding0, padding1, dilation0, dilation1, groups)// Lookup embeddings by index
embedded := mx.Embedding(weightMatrix, indices)// Norms
l2 := mx.NormL2(a, nil, false)
pNorm := mx.Norm(a, 2.0, nil, false)
// Decompositions
Q, R := mx.QR(a)
svdResult := mx.SVD(a, true) // Returns [U, S, Vt]
P, L, U := mx.LU(a)
chol := mx.Cholesky(a, false) // Lower triangular
// Matrix operations
inv := mx.Inv(a)
pinv := mx.PseudoInverse(a)
x := mx.Solve(A, b) // Solve Ax = b
// Eigenvalues
vals, vecs := mx.Eig(a)
vals := mx.EigVals(a)
// Cross product
cross := mx.Cross(a, b, axis)// Uniform distribution [low, high)
u := mx.RandomUniform(0, 1, []int32{3, 3}, mx.Float32)
// Normal distribution with mean=0, std=1
n := mx.RandomNormal([]int32{3, 3}, 0, 1, mx.Float32)
// Truncated normal
lower := mx.NewArrayFloat32(-2.0)
upper := mx.NewArrayFloat32(2.0)
tn := mx.RandomTruncatedNormal(lower, upper, []int32{3, 3}, mx.Float32)
// Random integers [low, high)
ints := mx.RandomRandint(0, 10, []int32{5}, mx.Int32)
// Random permutation
perm := mx.RandomPermutation(arr, axis)
// Categorical sampling from logits
samples := mx.RandomCategorical(logits, axis)
// Other distributions
gumbel := mx.RandomGumbel([]int32{3, 3}, mx.Float32)
laplace := mx.RandomLaplace([]int32{3, 3}, 0, 1, mx.Float32)// Default stream (GPU if available)
result := mx.Add(a, b) // Uses default stream
// Explicit GPU stream
result := mx.Add(a, b, mx.WithStream(mx.GPU))
// CPU stream
result := mx.Add(a, b, mx.WithStream(mx.CPU))Arrays are automatically garbage collected via Go's runtime. For explicit control:
arr := mx.FromSlice([]float32{1, 2, 3})
// ... use arr ...
arr.Free() // Optional: explicitly free C memoryMLX Go supports automatic gradient computation via Grad and ValueAndGrad:
// Define a differentiable function
loss := func(inputs ...mx.Array) []mx.Array {
pred := mx.Add(mx.MatMul(inputs[2], inputs[0]), inputs[1])
return []mx.Array{mx.Mean(mx.Square(mx.Subtract(pred, inputs[3])))}
}
// Compute gradients w.r.t. W (arg 0) and b (arg 1)
valueGradFn := mx.ValueAndGrad(loss, 0, 1)
values, grads := valueGradFn(W, b, X, Y)
// JIT compile for performance
fast := mx.Compile(loss)
fast = mx.Compile(loss, mx.Shapeless()) // shape-agnosticSee Autograd & Compilation for full documentation.
// To 1D slice
floats := mx.ToSlice2D[float32](arr)
// For 2D arrays, returns flattened data row-major
data := mx.ToSlice2D[float32](mat2d)package main
import (
"fmt"
mx "github.com/guptaaryan16/mlx_go/core"
)
func main() {
// Create data
X := mx.RandomUniform(0, 1, []int32{100, 10}, mx.Float32)
W := mx.RandomNormal([]int32{10, 5}, 0, 0.1, mx.Float32)
b := mx.Zeros([]int32{5}, mx.Float32)
// Forward pass: Y = ReLU(X @ W + b)
linear := mx.Add(mx.MatMul(X, W), b)
Y := mx.ReLU(linear)
Y.Eval()
fmt.Print("Output shape: ")
fmt.Println(Y.Shape()) // [100, 5]
}- See Autograd & Compilation for gradient computation and JIT compilation
- See Examples for complete working examples
- Check Indexing for array slicing and indexing