This directory contains end-to-end tests for the MLX backend. Each test verifies that a specific op or pattern is correctly lowered to MLX and produces matching outputs between PyTorch and the MLX runtime.
python install_executorch.py --editableFrom the ExecuTorch root directory:
cmake --preset mlx-release -DEXECUTORCH_BUILD_TESTS=ONThis configures the build with MLX delegate support and test targets. Build files are generated in cmake-out/.
cmake --build cmake-out --target op_test_runnerThis builds the op_test_runner binary that executes .pte models using the MLX runtime.
- Python environment: Tests must be run in an environment where the
executorchPython package is installed - Built C++ runtime: The
op_test_runnerbinary must be built (see Setup above)
To run all registered tests:
python -m executorch.backends.mlx.test.run_all_tests -j4 --clean-after| Flag | Description |
|---|---|
-j N / --parallel N |
Run tests in parallel with N workers |
--clean-after |
Clean up generated test files after running |
--clean |
Clean up generated test files and exit |
--rebuild |
Rebuild the C++ test runner before running |
--list |
List available tests and exit |
-v / --verbose |
Verbose output |
--timeout SECS |
Timeout per test in seconds (default: 300) |
Running many tests can accumulate memory (torch/MLX/Metal allocations). These flags help manage memory:
| Flag | Description |
|---|---|
--isolate |
Run each test in a separate subprocess (sequential mode only). Provides full memory isolation but is slower due to Python/torch import overhead per test. |
--max-tasks-per-worker N |
Recycle parallel workers after N tests (parallel mode only). Workers are terminated and replaced after completing N tests, releasing accumulated memory. |
Comparison:
| Mode | Memory Isolation | Speed |
|---|---|---|
-j 4 |
None (workers reused) | Fastest |
-j 4 --max-tasks-per-worker 10 |
Bounded (recycled every 10 tests) | Fast |
-j 4 --max-tasks-per-worker 1 |
Full (new process per test) | Slower |
--isolate |
Full (subprocess per test) | Slowest (sequential) |
Recommended for CI with memory constraints:
python -m executorch.backends.mlx.test.run_all_tests -j4 --max-tasks-per-worker 10 --clean-afterTo run a specific test by name (e.g., linear):
python -m executorch.backends.mlx.test.run_all_tests linearWith verbose output:
python -m executorch.backends.mlx.test.run_all_tests -v linearpython -m executorch.backends.mlx.test.run_all_tests --listAll tests are defined in test_ops.py. Each test follows a common pattern:
- Define a model - A simple
nn.Modulethat uses the op being tested - Create test inputs - Generate random input tensors
- Export and lower - Export the model and lower it to the MLX backend
- Run C++ binary - Execute the lowered model using
op_test_runner - Compare outputs - Verify PyTorch and MLX outputs match within tolerance
Tests inherit from OpTestCase and implement:
@register_test
class MyTest(OpTestCase):
name = "my_test" # Test name (used for output directory)
rtol = 1e-5 # Relative tolerance for comparison
atol = 1e-5 # Absolute tolerance for comparison
def create_model(self) -> nn.Module:
"""Return the model to test."""
...
def create_inputs(self) -> Tuple[torch.Tensor, ...]:
"""Return input tensors for export."""
...
def get_dynamic_shapes(self) -> Optional[Dict]:
"""Return dynamic shape specs, or None for static shapes."""
...
@classmethod
def get_test_configs(cls) -> List["MyTest"]:
"""Return list of test configurations to run."""
...Test artifacts are saved to op_tests/<test_name>/:
model.pte- Exported ExecuTorch modelinput.bin- Serialized input tensorsexpected_output.bin- PyTorch reference outputactual_output.bin- MLX runtime output
- Add a new model class and
OpTestCasesubclass totest_ops.py - Use the
@register_testdecorator on the test class - Implement
create_model(),create_inputs(), andget_test_configs() - Run the test to verify it works E2E
MLX also plugs into the ExecuTorch test harness for even more coverage. To run, use the following command from the ExecuTorch root directory:
pytest -c /dev/null backends/test/suite/operators/ -m flow_mlx