Files
2026-07-13 12:34:46 +08:00

45 lines
1.9 KiB
Python

#!/usr/bin/env python3
"""Basic usage example for Cider.
Demonstrates W8A8 and W4A8 quantized linear layers.
All operations return lazy mx.array — evaluated on mx.eval().
"""
import numpy as np
import mlx.core as mx
from cider import W8A8Linear, W4A8Linear, is_available
# Check hardware
if not is_available():
print("INT8 TensorOps not available (requires Apple M5+)")
exit(1)
print("INT8 TensorOps: available")
# ── Prepare weights ──────────────────────────────────────────────
K, N = 4096, 4096
W_fp16 = np.random.randn(K, N).astype(np.float16)
# ── W8A8 ─────────────────────────────────────────────────────────
w8a8 = W8A8Linear.from_weights(W_fp16)
print(f"W8A8: [{w8a8.input_dims}, {w8a8.output_dims}]")
x = mx.random.normal((32, K)).astype(mx.float16)
y = w8a8(x) # lazy — not computed yet
mx.eval(y) # now the GPU runs
print(f"W8A8 output: {y.shape}, dtype={y.dtype}")
# ── W4A8 ─────────────────────────────────────────────────────────
w4a8 = W4A8Linear.from_weights(W_fp16)
print(f"W4A8: [{w4a8.input_dims}, {w4a8.output_dims}]")
print(f"W4A8 weight storage: {w4a8.packed_weight.nbytes / 1024:.0f} KB "
f"(vs W8A8: {w8a8.weight.nbytes / 1024:.0f} KB)")
y4 = w4a8(x)
mx.eval(y4)
print(f"W4A8 output: {y4.shape}, dtype={y4.dtype}")
# ── Lazy composition ─────────────────────────────────────────────
# Multiple ops compose into a single MLX graph, evaluated together
z = w8a8(x) + w4a8(x) # builds graph, no GPU work yet
mx.eval(z) # single evaluation
print(f"Composed output: {z.shape}")