|
17 | 17 | from executorch.backends.arm.common.arm_compile_spec import ArmCompileSpec |
18 | 18 | from executorch.backends.arm.test import common |
19 | 19 | from executorch.backends.arm.test.runner_utils import dbg_tosa_fb_to_json |
| 20 | +from executorch.backends.arm.test.tester.arm_tester import ArmTester |
20 | 21 | from executorch.backends.arm.test.tester.test_pipeline import ( |
21 | 22 | EthosU55PipelineINT, |
22 | 23 | TosaPipelineFP, |
@@ -128,6 +129,59 @@ def test_tosa_FP_can_skip_ref_model_output_comparison(test_data: input_t1): |
128 | 129 | assert validation_compare_stage.kwargs["inputs"] == test_data |
129 | 130 |
|
130 | 131 |
|
| 132 | +@common.parametrize( |
| 133 | + "dtype_extension", |
| 134 | + { |
| 135 | + "e4m3": (torch.float8_e4m3fn, torch.float8_e4m3fn, "fp8e4m3"), |
| 136 | + "e5m2": (torch.float8_e5m2, torch.float8_e5m2, "fp8e5m2"), |
| 137 | + "e4m3_fp32": (torch.float8_e4m3fn, torch.float32, "fp8e4m3"), |
| 138 | + "fp32_e4m3": (torch.float32, torch.float8_e4m3fn, "fp8e4m3"), |
| 139 | + "e5m2_fp32": (torch.float8_e5m2, torch.float32, "fp8e5m2"), |
| 140 | + "fp32_e5m2": (torch.float32, torch.float8_e5m2, "fp8e5m2"), |
| 141 | + }, |
| 142 | +) |
| 143 | +def test_fp8_mismatch_reports_and_saves_diagnostics(dtype_extension, tmp_path, caplog): |
| 144 | + reference_dtype, result_dtype, extension = dtype_extension |
| 145 | + reference = ( |
| 146 | + torch.tensor([1.0, 2.0, 3.0, 4.0]).reshape(1, 2, 1, 2).to(reference_dtype) |
| 147 | + ) |
| 148 | + result = torch.tensor([1.0, 2.0, 4.0, 5.0]).reshape(1, 2, 1, 2).to(result_dtype) |
| 149 | + tester = ArmTester( |
| 150 | + torch.nn.Identity(), |
| 151 | + (reference,), |
| 152 | + common.get_vgf_compile_spec( |
| 153 | + f"TOSA-1.0+FP+{extension}", custom_path=str(tmp_path) |
| 154 | + ), |
| 155 | + ) |
| 156 | + |
| 157 | + # The base comparator only widens inputs when the result is FP8. |
| 158 | + def compare_in_fp32(reference, result, _): |
| 159 | + ArmTester._assert_outputs_equal( |
| 160 | + [result.float()], [reference.float()], atol=0, rtol=0 |
| 161 | + ) |
| 162 | + |
| 163 | + with pytest.raises( |
| 164 | + AssertionError, match="Output 0 does not match reference output" |
| 165 | + ): |
| 166 | + tester._compare_outputs( |
| 167 | + reference, |
| 168 | + result, |
| 169 | + atol=0, |
| 170 | + rtol=0, |
| 171 | + compare_callback=compare_in_fp32 if result_dtype == torch.float32 else None, |
| 172 | + ) |
| 173 | + |
| 174 | + assert "ERROR DIFFERENCE" in caplog.text |
| 175 | + assert "MEAN MEDIAN MAX MIN" in caplog.text |
| 176 | + for filename, expected in ( |
| 177 | + ("torch_tosa_output.pt", result), |
| 178 | + ("torch_ref_output.pt", reference), |
| 179 | + ): |
| 180 | + saved = torch.load(tmp_path / filename, weights_only=True) |
| 181 | + assert saved.dtype == expected.dtype |
| 182 | + torch.testing.assert_close(saved.float(), expected.float(), atol=0, rtol=0) |
| 183 | + |
| 184 | + |
131 | 185 | @common.parametrize("test_data", Linear.inputs) |
132 | 186 | def test_artifact_tosa_FP(test_data: input_t1): |
133 | 187 | model = Linear() |
|
0 commit comments