Skip to content

Commit 70594d3

Browse files
authored
Arm backend: Keep DeepSeek FP8 on xlarge path (#21612)
Keep the DeepSeek-R1-Distill-Qwen-1.5B FP8 layer tests on the existing generic xlarge TOSA and VKML model suites. This drops the dedicated DeepSeek job wiring added in the previous patchset and follows the existing Arm backend model for memory-heavy coverage: smaller cases stay in the normal shard and heavy cases run through the serialised xlarge path. That keeps the FP8 coverage in CI without introducing DeepSeek-specific test entrypoints or workflow jobs. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani
1 parent 28a7fac commit 70594d3

1 file changed

Lines changed: 196 additions & 24 deletions

File tree

backends/arm/test/models/DeepSeek_R1_Distill_Qwen/test_deepseek_r1_distill_qwen_layers.py

Lines changed: 196 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010

1111
import pytest
1212
import torch
13+
from executorch.backends.arm.ao_ext import MXFPOpConfig
1314
from executorch.backends.arm.test import common
1415
from executorch.backends.arm.test.models.DeepSeek_R1_Distill_Qwen.deepseek_r1_distill_qwen_test_config import (
1516
get_deepseek_r1_distill_qwen_1_5b_checkpoint_config,
1617
)
18+
from executorch.backends.arm.test.ops.mxfp.common import MXFPTosaPipelineFP
1719
from executorch.backends.arm.test.tester.test_pipeline import (
1820
TosaPipelineFP,
1921
VgfPipeline,
@@ -32,6 +34,7 @@
3234
)
3335

3436
input_t = Tuple[torch.Tensor, ...]
37+
aten_op_mxfp_linear = "torch.ops.tosa_mxfp.linear.default"
3538

3639

3740
def _make_deepseek_r1_distill_qwen_1_5b_layer_config():
@@ -84,6 +87,10 @@ def _to_bfloat16(
8487
)
8588

8689

90+
def _is_linear(module: torch.nn.Module, _fqn: str) -> bool:
91+
return isinstance(module, torch.nn.Linear)
92+
93+
8794
class RotaryEmbeddingModel(DeepSeekR1DistillQwenTestModule):
8895
def __init__(self, config) -> None:
8996
super().__init__()
@@ -257,18 +264,21 @@ class DeepSeekR1DistillQwenTestCase:
257264
transform_passes: tuple = field(default_factory=tuple)
258265

259266

260-
TOSA_FP_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
267+
TOSA_FP_SMALL_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
261268
"rotary_embedding": DeepSeekR1DistillQwenTestCase(model_cls=RotaryEmbeddingModel),
262269
"rotary_apply": DeepSeekR1DistillQwenTestCase(model_cls=RotaryApplyModel),
263270
"repeat_kv": DeepSeekR1DistillQwenTestCase(model_cls=RepeatKVModel),
264-
"attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel),
265271
"rms_norm": DeepSeekR1DistillQwenTestCase(model_cls=RMSNormModel),
272+
"final_norm": DeepSeekR1DistillQwenTestCase(model_cls=FinalNormModel),
273+
}
274+
275+
TOSA_FP_XLARGE_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
276+
"attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel),
266277
"mlp": DeepSeekR1DistillQwenTestCase(model_cls=MLPModel),
267278
"decoder_layer": DeepSeekR1DistillQwenTestCase(model_cls=DecoderLayerModel),
268-
"final_norm": DeepSeekR1DistillQwenTestCase(model_cls=FinalNormModel),
269279
}
270280

271-
TOSA_BF16_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
281+
TOSA_BF16_SMALL_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
272282
"rotary_embedding": DeepSeekR1DistillQwenTestCase(
273283
model_cls=RotaryEmbeddingModel,
274284
atol=1e-2,
@@ -284,13 +294,21 @@ class DeepSeekR1DistillQwenTestCase:
284294
atol=1e-2,
285295
rtol=1e-2,
286296
),
287-
"attention": DeepSeekR1DistillQwenTestCase(
288-
model_cls=AttentionModel,
297+
"rms_norm": DeepSeekR1DistillQwenTestCase(
298+
model_cls=RMSNormModel,
289299
atol=1e-2,
290300
rtol=1e-2,
291301
),
292-
"rms_norm": DeepSeekR1DistillQwenTestCase(
293-
model_cls=RMSNormModel,
302+
"final_norm": DeepSeekR1DistillQwenTestCase(
303+
model_cls=FinalNormModel,
304+
atol=1e-2,
305+
rtol=1e-2,
306+
),
307+
}
308+
309+
TOSA_BF16_XLARGE_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
310+
"attention": DeepSeekR1DistillQwenTestCase(
311+
model_cls=AttentionModel,
294312
atol=1e-2,
295313
rtol=1e-2,
296314
),
@@ -304,33 +322,40 @@ class DeepSeekR1DistillQwenTestCase:
304322
atol=1e-2,
305323
rtol=1e-2,
306324
),
307-
"final_norm": DeepSeekR1DistillQwenTestCase(
308-
model_cls=FinalNormModel,
309-
atol=1e-2,
310-
rtol=1e-2,
311-
),
312325
}
313326

314-
VGF_NO_QUANT_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
327+
VGF_NO_QUANT_SMALL_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
315328
"rotary_embedding": DeepSeekR1DistillQwenTestCase(model_cls=RotaryEmbeddingModel),
316329
"rotary_apply": DeepSeekR1DistillQwenTestCase(model_cls=RotaryApplyModel),
317330
"repeat_kv": DeepSeekR1DistillQwenTestCase(model_cls=RepeatKVModel),
318-
"attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel),
319331
"rms_norm": DeepSeekR1DistillQwenTestCase(model_cls=RMSNormModel),
332+
"final_norm": DeepSeekR1DistillQwenTestCase(model_cls=FinalNormModel),
333+
}
334+
335+
VGF_NO_QUANT_XLARGE_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
336+
"attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel),
320337
"mlp": DeepSeekR1DistillQwenTestCase(model_cls=MLPModel),
321338
"decoder_layer": DeepSeekR1DistillQwenTestCase(model_cls=DecoderLayerModel),
322-
"final_norm": DeepSeekR1DistillQwenTestCase(model_cls=FinalNormModel),
323339
}
324340

325-
VGF_NO_QUANT_BF16_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = (
326-
TOSA_BF16_TEST_CASES
341+
VGF_NO_QUANT_BF16_SMALL_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = (
342+
TOSA_BF16_SMALL_TEST_CASES
327343
)
328344

345+
VGF_NO_QUANT_BF16_XLARGE_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = (
346+
TOSA_BF16_XLARGE_TEST_CASES
347+
)
348+
349+
TOSA_MXFP8_TEST_CASES: dict[str, DeepSeekR1DistillQwenTestCase] = {
350+
"attention": DeepSeekR1DistillQwenTestCase(model_cls=AttentionModel),
351+
"mlp": DeepSeekR1DistillQwenTestCase(model_cls=MLPModel),
352+
"decoder_layer": DeepSeekR1DistillQwenTestCase(model_cls=DecoderLayerModel),
353+
}
354+
329355

330-
@pytest.mark.xlarge
331356
@common.parametrize(
332357
"test_case",
333-
TOSA_FP_TEST_CASES,
358+
TOSA_FP_SMALL_TEST_CASES,
334359
)
335360
def test_deepseek_r1_distill_qwen_tosa_FP(
336361
test_case: DeepSeekR1DistillQwenTestCase,
@@ -350,7 +375,50 @@ def test_deepseek_r1_distill_qwen_tosa_FP(
350375
@pytest.mark.xlarge
351376
@common.parametrize(
352377
"test_case",
353-
TOSA_BF16_TEST_CASES,
378+
TOSA_FP_XLARGE_TEST_CASES,
379+
)
380+
def test_deepseek_r1_distill_qwen_tosa_FP_xlarge(
381+
test_case: DeepSeekR1DistillQwenTestCase,
382+
):
383+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
384+
with torch.no_grad():
385+
pipeline = TosaPipelineFP[input_t](
386+
model,
387+
inputs,
388+
aten_op=[],
389+
exir_op=[],
390+
transform_passes=list(test_case.transform_passes),
391+
)
392+
pipeline.run()
393+
394+
395+
@pytest.mark.xlarge
396+
@common.parametrize(
397+
"test_case",
398+
TOSA_BF16_XLARGE_TEST_CASES,
399+
)
400+
def test_deepseek_r1_distill_qwen_tosa_FP_bf16_xlarge(
401+
test_case: DeepSeekR1DistillQwenTestCase,
402+
):
403+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
404+
model, inputs = _to_bfloat16(model, inputs)
405+
with torch.no_grad():
406+
pipeline = TosaPipelineFP[input_t](
407+
model,
408+
inputs,
409+
aten_op=[],
410+
exir_op=[],
411+
transform_passes=list(test_case.transform_passes),
412+
tosa_extensions=["bf16"],
413+
atol=test_case.atol,
414+
rtol=test_case.rtol,
415+
)
416+
pipeline.run()
417+
418+
419+
@common.parametrize(
420+
"test_case",
421+
TOSA_BF16_SMALL_TEST_CASES,
354422
)
355423
def test_deepseek_r1_distill_qwen_tosa_FP_bf16(
356424
test_case: DeepSeekR1DistillQwenTestCase,
@@ -372,10 +440,89 @@ def test_deepseek_r1_distill_qwen_tosa_FP_bf16(
372440

373441

374442
@pytest.mark.xlarge
443+
@common.parametrize(
444+
"test_case",
445+
TOSA_MXFP8_TEST_CASES,
446+
)
447+
def test_deepseek_r1_distill_qwen_tosa_mxfp8_fp32(
448+
test_case: DeepSeekR1DistillQwenTestCase,
449+
):
450+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
451+
mxfp_config = MXFPOpConfig(weight_dtype=torch.float8_e4m3fn)
452+
453+
with torch.no_grad():
454+
pipeline = MXFPTosaPipelineFP[input_t](
455+
model,
456+
inputs,
457+
aten_op=aten_op_mxfp_linear,
458+
exir_op=[],
459+
filter_fn=_is_linear,
460+
frobenius_threshold=0.05,
461+
cosine_threshold=0.995,
462+
mxfp_config=mxfp_config,
463+
tosa_version="1.1",
464+
tosa_extensions=["mxfp"],
465+
)
466+
pipeline.run()
467+
468+
469+
@pytest.mark.xlarge
470+
@common.parametrize(
471+
"test_case",
472+
TOSA_MXFP8_TEST_CASES,
473+
)
474+
def test_deepseek_r1_distill_qwen_tosa_mxfp8_bf16(
475+
test_case: DeepSeekR1DistillQwenTestCase,
476+
):
477+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
478+
model, inputs = _to_bfloat16(model, inputs)
479+
mxfp_config = MXFPOpConfig(weight_dtype=torch.float8_e4m3fn)
480+
481+
with torch.no_grad():
482+
pipeline = MXFPTosaPipelineFP[input_t](
483+
model,
484+
inputs,
485+
aten_op=aten_op_mxfp_linear,
486+
exir_op=[],
487+
filter_fn=_is_linear,
488+
frobenius_threshold=0.05,
489+
cosine_threshold=0.995,
490+
mxfp_config=mxfp_config,
491+
tosa_version="1.1",
492+
tosa_extensions=["bf16", "mxfp"],
493+
)
494+
pipeline.run()
495+
496+
497+
@pytest.mark.xlarge
498+
@common.SkipIfNoModelConverter
499+
@common.parametrize(
500+
"test_case",
501+
VGF_NO_QUANT_XLARGE_TEST_CASES,
502+
)
503+
def test_deepseek_r1_distill_qwen_vgf_no_quant_xlarge(
504+
test_case: DeepSeekR1DistillQwenTestCase,
505+
):
506+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
507+
with torch.no_grad():
508+
pipeline = VgfPipeline[input_t](
509+
model,
510+
inputs,
511+
aten_op=[],
512+
exir_op=[],
513+
quantize=False,
514+
atol=test_case.atol,
515+
rtol=test_case.rtol,
516+
qtol=test_case.qtol,
517+
transform_passes=list(test_case.transform_passes),
518+
)
519+
pipeline.run()
520+
521+
375522
@common.SkipIfNoModelConverter
376523
@common.parametrize(
377524
"test_case",
378-
VGF_NO_QUANT_TEST_CASES,
525+
VGF_NO_QUANT_SMALL_TEST_CASES,
379526
)
380527
def test_deepseek_r1_distill_qwen_vgf_no_quant(
381528
test_case: DeepSeekR1DistillQwenTestCase,
@@ -396,11 +543,10 @@ def test_deepseek_r1_distill_qwen_vgf_no_quant(
396543
pipeline.run()
397544

398545

399-
@pytest.mark.xlarge
400546
@common.SkipIfNoModelConverter
401547
@common.parametrize(
402548
"test_case",
403-
VGF_NO_QUANT_BF16_TEST_CASES,
549+
VGF_NO_QUANT_BF16_SMALL_TEST_CASES,
404550
)
405551
def test_deepseek_r1_distill_qwen_vgf_no_quant_bf16(
406552
test_case: DeepSeekR1DistillQwenTestCase,
@@ -420,3 +566,29 @@ def test_deepseek_r1_distill_qwen_vgf_no_quant_bf16(
420566
transform_passes=list(test_case.transform_passes),
421567
)
422568
pipeline.run()
569+
570+
571+
@pytest.mark.xlarge
572+
@common.SkipIfNoModelConverter
573+
@common.parametrize(
574+
"test_case",
575+
VGF_NO_QUANT_BF16_XLARGE_TEST_CASES,
576+
)
577+
def test_deepseek_r1_distill_qwen_vgf_no_quant_bf16_xlarge(
578+
test_case: DeepSeekR1DistillQwenTestCase,
579+
):
580+
model, inputs = test_case.model_cls.prepare_model_and_inputs()
581+
model, inputs = _to_bfloat16(model, inputs)
582+
with torch.no_grad():
583+
pipeline = VgfPipeline[input_t](
584+
model,
585+
inputs,
586+
aten_op=[],
587+
exir_op=[],
588+
quantize=False,
589+
atol=test_case.atol,
590+
rtol=test_case.rtol,
591+
qtol=test_case.qtol,
592+
transform_passes=list(test_case.transform_passes),
593+
)
594+
pipeline.run()

0 commit comments

Comments
 (0)