|
10 | 10 |
|
11 | 11 | import pytest |
12 | 12 | import torch |
| 13 | +from executorch.backends.arm.ao_ext import MXFPOpConfig |
13 | 14 | from executorch.backends.arm.test import common |
14 | 15 | from executorch.backends.arm.test.models.DeepSeek_R1_Distill_Qwen.deepseek_r1_distill_qwen_test_config import ( |
15 | 16 | get_deepseek_r1_distill_qwen_1_5b_checkpoint_config, |
16 | 17 | ) |
| 18 | +from executorch.backends.arm.test.ops.mxfp.common import MXFPTosaPipelineFP |
17 | 19 | from executorch.backends.arm.test.tester.test_pipeline import ( |
18 | 20 | TosaPipelineFP, |
19 | 21 | VgfPipeline, |
|
32 | 34 | ) |
33 | 35 |
|
34 | 36 | input_t = Tuple[torch.Tensor, ...] |
| 37 | +aten_op_mxfp_linear = "torch.ops.tosa_mxfp.linear.default" |
35 | 38 |
|
36 | 39 |
|
37 | 40 | def _make_deepseek_r1_distill_qwen_1_5b_layer_config(): |
@@ -84,6 +87,10 @@ def _to_bfloat16( |
84 | 87 | ) |
85 | 88 |
|
86 | 89 |
|
| 90 | +def _is_linear(module: torch.nn.Module, _fqn: str) -> bool: |
| 91 | + return isinstance(module, torch.nn.Linear) |
| 92 | + |
| 93 | + |
87 | 94 | class RotaryEmbeddingModel(DeepSeekR1DistillQwenTestModule): |
88 | 95 | def __init__(self, config) -> None: |
89 | 96 | super().__init__() |
@@ -326,6 +333,12 @@ class DeepSeekR1DistillQwenTestCase: |
326 | 333 | TOSA_BF16_TEST_CASES |
327 | 334 | ) |
328 | 335 |
|
| 336 | +TOSA_MXFP8_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = { |
| 337 | + "attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel), |
| 338 | + "mlp": DeepSeekR1DistillQwenTestCase(model_cls=MLPModel), |
| 339 | + "decoder_layer": DeepSeekR1DistillQwenTestCase(model_cls=DecoderLayerModel), |
| 340 | +} |
| 341 | + |
329 | 342 |
|
330 | 343 | @common.parametrize( |
331 | 344 | "test_case", |
@@ -369,6 +382,59 @@ def test_deepseek_r1_distill_qwen_tosa_FP_bf16( |
369 | 382 | pipeline.run() |
370 | 383 |
|
371 | 384 |
|
| 385 | +@common.parametrize( |
| 386 | + "test_case", |
| 387 | + TOSA_MXFP8_TEST_CASES, |
| 388 | +) |
| 389 | +def test_deepseek_r1_distill_qwen_tosa_mxfp8_fp32( |
| 390 | + test_case: DeepSeekR1DistillQwenTestCase, |
| 391 | +): |
| 392 | + model, inputs = test_case.model_cls.prepare_model_and_inputs() |
| 393 | + mxfp_config = MXFPOpConfig(weight_dtype=torch.float8_e4m3fn) |
| 394 | + |
| 395 | + with torch.no_grad(): |
| 396 | + pipeline = MXFPTosaPipelineFP[input_t]( |
| 397 | + model, |
| 398 | + inputs, |
| 399 | + aten_op=aten_op_mxfp_linear, |
| 400 | + exir_op=[], |
| 401 | + filter_fn=_is_linear, |
| 402 | + frobenius_threshold=0.05, |
| 403 | + cosine_threshold=0.995, |
| 404 | + mxfp_config=mxfp_config, |
| 405 | + tosa_version="1.1", |
| 406 | + tosa_extensions=["mxfp"], |
| 407 | + ) |
| 408 | + pipeline.run() |
| 409 | + |
| 410 | + |
| 411 | +@common.parametrize( |
| 412 | + "test_case", |
| 413 | + TOSA_MXFP8_TEST_CASES, |
| 414 | +) |
| 415 | +def test_deepseek_r1_distill_qwen_tosa_mxfp8_bf16( |
| 416 | + test_case: DeepSeekR1DistillQwenTestCase, |
| 417 | +): |
| 418 | + model, inputs = test_case.model_cls.prepare_model_and_inputs() |
| 419 | + model, inputs = _to_bfloat16(model, inputs) |
| 420 | + mxfp_config = MXFPOpConfig(weight_dtype=torch.float8_e4m3fn) |
| 421 | + |
| 422 | + with torch.no_grad(): |
| 423 | + pipeline = MXFPTosaPipelineFP[input_t]( |
| 424 | + model, |
| 425 | + inputs, |
| 426 | + aten_op=aten_op_mxfp_linear, |
| 427 | + exir_op=[], |
| 428 | + filter_fn=_is_linear, |
| 429 | + frobenius_threshold=0.05, |
| 430 | + cosine_threshold=0.995, |
| 431 | + mxfp_config=mxfp_config, |
| 432 | + tosa_version="1.1", |
| 433 | + tosa_extensions=["bf16", "mxfp"], |
| 434 | + ) |
| 435 | + pipeline.run() |
| 436 | + |
| 437 | + |
372 | 438 | @common.SkipIfNoModelConverter |
373 | 439 | @common.parametrize( |
374 | 440 | "test_case", |
|
0 commit comments