Files
ma-jh 124fb8a2a4 feat: add LigerMLP module (#1357)
## Summary
Add LigerMLP, a Triton-based fused SwiGLU MLP that co-optimizes the
complete forward and backward dataflow rather than only the element-wise
SiLU-and-gating stage.

Linked issue: #1347

## Details
When running `make test`, an `xfail` occurs. This is not due to an error
in the operator implementation, but because in
`test_misaligned_intermediate_size_not_supported`, the
`intermediate_size` is set to 431, which does not satisfy Triton's
`TensorDescriptor` requirement of 16‑byte alignment.
Additionally, since this implementation uses `tl.dot`, when the input
data type is `fp32`, `tl.dot` performs computations using `tf32`
internally, which differs from PyTorch's behavior of using pure `fp32`
for computation. As a result, the numerical error between this
implementation and the reference implementation is relatively larger.
Therefore, when the data type is `fp32`, the tolerance range is set to a
larger value.


## Testing Done

- Hardware Type: RTX 5060ti 16G(SM120)
- [x] run `make test` to ensure correctness
- [x] run `make checkstyle` to ensure code style
- [ ] run `make test-convergence` to ensure convergence

```
python -m pytest test/transformers/test_mlp.py
================================================================================================== test session starts ===================================================================================================
platform linux -- Python 3.12.3, pytest-9.0.2, pluggy-1.6.0
rootdir: /home/ma-jh/Liger-Kernel
configfile: pyproject.toml
plugins: rerunfailures-16.4, asyncio-1.4.0, xdist-3.8.0, anyio-4.12.0, cov-7.1.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function
collected 24 items                                                                                                                                                                                                       

test/transformers/test_mlp.py::test_correctness_llamamlp[dtype0-200.0-0.02-2-256-256-512] PASSED                                                                                                                   [  4%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype0-200.0-0.02-6-42-128-432] PASSED                                                                                                                    [  8%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype0-200.0-0.02-3-37-96-264] PASSED                                                                                                                     [ 12%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype1-10000.0-0.01-2-256-256-512] PASSED                                                                                                                 [ 16%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype1-10000.0-0.01-6-42-128-432] PASSED                                                                                                                  [ 20%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype1-10000.0-0.01-3-37-96-264] PASSED                                                                                                                   [ 25%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype2-100.0-0.01-2-256-256-512] PASSED                                                                                                                   [ 29%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype2-100.0-0.01-6-42-128-432] PASSED                                                                                                                    [ 33%]
test/transformers/test_mlp.py::test_correctness_llamamlp[dtype2-100.0-0.01-3-37-96-264] PASSED                                                                                                                     [ 37%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype0-200.0-0.02-2-256-256-512] PASSED                                                                                                             [ 41%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype0-200.0-0.02-6-42-128-432] PASSED                                                                                                              [ 45%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype0-200.0-0.02-3-37-96-264] PASSED                                                                                                               [ 50%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype1-10000.0-0.01-2-256-256-512] PASSED                                                                                                           [ 54%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype1-10000.0-0.01-6-42-128-432] PASSED                                                                                                            [ 58%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype1-10000.0-0.01-3-37-96-264] PASSED                                                                                                             [ 62%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype2-100.0-0.01-2-256-256-512] PASSED                                                                                                             [ 66%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype2-100.0-0.01-6-42-128-432] PASSED                                                                                                              [ 70%]
test/transformers/test_mlp.py::test_correctness_inference_mode[dtype2-100.0-0.01-3-37-96-264] PASSED                                                                                                               [ 75%]
test/transformers/test_mlp.py::test_invalid_hidden_act_raises[gelu] PASSED                                                                                                                                         [ 79%]
test/transformers/test_mlp.py::test_invalid_hidden_act_raises[relu] PASSED                                                                                                                                         [ 83%]
test/transformers/test_mlp.py::test_invalid_hidden_act_raises[tanh] PASSED                                                                                                                                         [ 87%]
test/transformers/test_mlp.py::test_supported_hidden_act[silu] PASSED                                                                                                                                              [ 91%]
test/transformers/test_mlp.py::test_supported_hidden_act[swish] PASSED                                                                                                                                             [ 95%]
test/transformers/test_mlp.py::test_misaligned_intermediate_size_not_supported XFAIL (TMA descriptors require 3 * intermediate_size * elem_bytes to be 16-byte aligned; intermediate_size=431 with bf16 (strid...) [100%]
```

```
make checkstyle
ruff check --output-format=concise .; ruff_check_status=$?; \
ruff format --check --diff .; ruff_format_status=$?; \
ruff check . --fix; \
ruff format .; \
if [ $ruff_check_status -ne 0 ] || [ $ruff_format_status -ne 0 ]; then \
        exit 1; \
fi
All checks passed!
354 files already formatted
All checks passed!
354 files left unchanged
```

---------

Signed-off-by: pearblossom <[email protected]>
Signed-off-by: ma-jh <[email protected]>
2026-08-20 03:07:52 +00:00

111 lines
3.5 KiB
Python

import torch
from benchmark_model_configs import MODEL_REGISTRY
from benchmark_model_configs import build_model_config_sweep
from benchmark_model_configs import build_token_length_sweep
from benchmark_model_configs import get_benchmark_model_config
from transformers.models.llama.configuration_llama import LlamaConfig
from transformers.models.llama.modeling_llama import LlamaMLP
from utils import SingleBenchmarkRunInput
from utils import build_memory_bench_fn
from utils import build_speed_bench_fn
from utils import parse_benchmark_script_args
from utils import run_benchmarks
from liger_kernel.transformers.mlp import LigerMLP
from liger_kernel.utils import infer_device
device = infer_device()
def setup_mlp(input: SingleBenchmarkRunInput):
"""Create input tensor and SwiGLU MLP layer from benchmark config."""
cfg = input.extra_benchmark_config
if isinstance(input.x, str):
model_cfg = MODEL_REGISTRY[input.x]
seq_len = cfg["seq_len"]
hidden_size = model_cfg.hidden_size
intermediate_size = model_cfg.intermediate_size
dtype = model_cfg.dtype
else:
seq_len = input.x
hidden_size = cfg["hidden_size"]
intermediate_size = cfg["intermediate_size"]
dtype = cfg["dtype"]
llama_config = LlamaConfig(
hidden_size=hidden_size,
intermediate_size=intermediate_size,
hidden_act=cfg["hidden_act"],
)
x = torch.randn(
cfg["bsz"],
seq_len,
hidden_size,
device=device,
dtype=dtype,
requires_grad=True,
)
if input.kernel_provider == "liger":
layer = LigerMLP(config=llama_config).to(device).to(dtype)
elif input.kernel_provider == "huggingface":
layer = LlamaMLP(config=llama_config).to(device).to(dtype)
else:
raise ValueError(f"Invalid provider: {input.kernel_provider} for MLP")
return x, layer
if __name__ == "__main__":
args = parse_benchmark_script_args()
if args.sweep_mode == "model_config":
common_configs = build_model_config_sweep(
kernel_name="mlp",
setup_fn=setup_mlp,
model_keys=["hidden_size", "intermediate_size", "dtype"],
probe_provider="huggingface",
extra_configs={
"bsz": 1,
"hidden_act": "silu",
},
probe_dim="T",
bt=args.bt,
overwrite=args.overwrite,
)
else:
model = get_benchmark_model_config(args.model)
probe_seq_len = 1024
common_configs = build_token_length_sweep(
kernel_name="mlp",
probe_x=probe_seq_len,
model=model,
setup_fn=setup_mlp,
model_keys=["hidden_size", "intermediate_size", "dtype"],
extra_configs={
"bsz": 1,
"hidden_act": "silu",
},
scale_dim="T",
x_label="total tokens",
probe_provider="huggingface",
overwrite=args.overwrite,
)
common_configs["kernel_providers"] = ["huggingface", "liger"]
run_benchmarks(
bench_test_fn=build_speed_bench_fn(setup_mlp),
kernel_operation_modes=["forward", "backward", "full"],
metric_name="speed",
metric_unit="ms",
**common_configs,
)
run_benchmarks(
bench_test_fn=build_memory_bench_fn(setup_mlp),
kernel_operation_modes=["full", "forward", "backward"],
metric_name="memory",
metric_unit="MB",
**common_configs,
)