MiniMax-H3-Image-mlx / tests /test_tuning.py
devin-lai's picture
Release v0.4.0: selective MLX model downloads
3da88e3 verified
Raw History Blame Contribute Delete
3.04 kB
import mlx.core as mx
import numpy as np
import pytest
from h3_mlx.ops import modulate, rms_norm, rotate
from h3_mlx.tuning import (
TunedFC2,
_gemm,
norm_modulate_exact,
qk_norm_rope_exact,
supported_device,
)
from h3_mlx.weights import Linear
@pytest.mark.parametrize("magnitude", [0.001, 1.0, 10000.0])
@pytest.mark.parametrize("rope_dtype", [mx.bfloat16, mx.float32])
@pytest.mark.skipif(
not supported_device(), reason="Pinned M5 Pro/MLX kernel validation"
)
def test_qk_fusion_preserves_native_reduction_and_rope_bits(magnitude, rope_dtype):
mx.random.seed(8192)
qkv = (mx.random.normal((37, 3, 3, 128)) * magnitude).astype(mx.bfloat16)
qw = mx.random.normal((128,)).astype(mx.bfloat16)
kw = mx.random.normal((128,)).astype(mx.bfloat16)
angles = mx.random.normal((1, 37, 1, 48))
angles = mx.concatenate((angles, angles), axis=-1)
cosine = mx.cos(angles).astype(rope_dtype)
sine = mx.sin(angles).astype(rope_dtype)
reference = tuple(
rotate(rms_norm(qkv[None, :, i], w), cosine, sine)
for i, w in ((0, qw), (1, kw))
)
result = qk_norm_rope_exact(qkv, qw, kw, cosine, sine)
for expected, actual in zip(reference, result, strict=True):
np.testing.assert_array_equal(
np.asarray(actual.view(mx.uint16)), np.asarray(expected.view(mx.uint16))
)
@pytest.mark.skipif(not supported_device(), reason="Metal 4 M5 kernel validation")
def test_mpp_fp32_bias_epilogue_and_partial_m_tile():
mx.random.seed(4352)
x = (mx.random.normal((71, 512)) * 32).astype(mx.bfloat16)
weight = (mx.random.normal((256, 512)) * 0.02).astype(mx.bfloat16)
bias = mx.random.normal((256,)).astype(mx.bfloat16)
expected = mx.addmm(bias, x, weight.T)
actual = _gemm(x, weight, bias, 64, 128, 128, 4, 8)
np.testing.assert_array_equal(
np.asarray(actual.view(mx.uint16)), np.asarray(expected.view(mx.uint16))
)
def test_tuned_fc2_keeps_native_fallback_for_unsupported_shapes():
mx.random.seed(71)
layer = Linear(mx.random.normal((32, 64)).astype(mx.bfloat16))
x = mx.random.normal((17, 64)).astype(mx.bfloat16)
tuned = TunedFC2(layer)
np.testing.assert_array_equal(
np.asarray(tuned(x).view(mx.uint16)), np.asarray(layer(x).view(mx.uint16))
)
@pytest.mark.skipif(not supported_device(), reason="Pinned M5 Pro reduction layout")
def test_full_width_norm_fusion_matches_native_loop_and_bf16_boundaries():
mx.random.seed(5376)
x = (mx.random.normal((13, 5376)) * 256).astype(mx.bfloat16)
weight = mx.random.normal((5376,)).astype(mx.bfloat16)
shift = mx.random.normal((6, 5376)).astype(mx.bfloat16)
scale = (mx.random.normal((6, 5376)) * 0.1).astype(mx.bfloat16)
indices = mx.arange(13, dtype=mx.int32) % 6
expected = modulate(x, weight, shift, scale, indices)
actual = norm_modulate_exact(x, weight, shift, scale, indices)
np.testing.assert_array_equal(
np.asarray(actual.view(mx.uint16)), np.asarray(expected.view(mx.uint16))
)