|
6 | 6 | from typing import Optional, Tuple |
7 | 7 |
|
8 | 8 | import torch |
| 9 | +from executorch.backends.arm.operator_support.ethos_u55_support import ( |
| 10 | + EthosU55ResizeCheck, |
| 11 | +) |
9 | 12 | from executorch.backends.arm.quantizer.arm_quantizer import ( |
10 | 13 | get_symmetric_a16w8_quantization_config, |
11 | 14 | ) |
12 | 15 | from executorch.backends.arm.test import common |
| 16 | +from executorch.backends.arm.test.tester.arm_tester import ArmTester |
13 | 17 |
|
14 | 18 | from executorch.backends.arm.test.tester.test_pipeline import ( |
| 19 | + EthosU55PipelineINT, |
15 | 20 | OpNotSupportedPipeline, |
16 | 21 | TosaPipelineFP, |
17 | 22 | TosaPipelineINT, |
18 | 23 | VgfPipeline, |
19 | 24 | ) |
| 25 | +from executorch.exir.backend.utils import WhyNoPartitionReporter |
| 26 | +from executorch.exir.dialects._ops import ops as exir_ops |
20 | 27 |
|
21 | 28 | aten_op = "torch.ops.aten.upsample_nearest2d.vec" |
22 | 29 | exir_op = "executorch_exir_dialects_edge__ops_aten_upsample_nearest2d_vec" |
|
75 | 82 | } |
76 | 83 |
|
77 | 84 | test_data_u55 = { |
78 | | - "rand_double_size": lambda: (torch.rand(2, 4, 8, 3), (16, 6), None, True), |
| 85 | + "rand_double_scale": lambda: (torch.rand(1, 4, 8, 3), None, 2.0, True), |
| 86 | + "rand_double_scale_different_shape": lambda: ( |
| 87 | + torch.rand(1, 2, 4, 3), |
| 88 | + None, |
| 89 | + 2.0, |
| 90 | + True, |
| 91 | + ), |
| 92 | + "rand_quadruple_size": lambda: (torch.rand(1, 4, 8, 3), (32, 12), None, True), |
| 93 | + "rand_octuple_size": lambda: (torch.rand(1, 4, 8, 3), (64, 24), None, True), |
79 | 94 | } |
80 | 95 |
|
81 | 96 | test_data_suite_dynamic = { |
@@ -447,58 +462,120 @@ def test_upsample_nearest2d_vec_vgf_quant_a16w8_interpolate( |
447 | 462 |
|
448 | 463 | @common.parametrize("test_data", test_data_u55) |
449 | 464 | @common.XfailIfNoCorstone300 |
450 | | -def test_upsample_nearest2d_vec_u55_INT_Upsample_not_delegated( |
451 | | - test_data: torch.Tensor, |
452 | | -): |
| 465 | +def test_upsample_nearest2d_vec_u55_INT_Upsample(test_data: torch.Tensor): |
453 | 466 | test_data, size, scale_factor, compare_outputs = test_data() |
454 | | - pipeline = OpNotSupportedPipeline[input_t1]( |
| 467 | + pipeline = EthosU55PipelineINT[input_t1]( |
455 | 468 | Upsample(size, scale_factor), |
456 | 469 | (test_data,), |
457 | | - {exir_op: 1}, |
458 | | - n_expected_delegates=0, |
459 | | - quantize=True, |
460 | | - u55_subset=True, |
| 470 | + aten_op, |
| 471 | + exir_op, |
461 | 472 | ) |
| 473 | + pipeline.run() |
462 | 474 |
|
| 475 | + |
| 476 | +@common.parametrize("test_data", test_data_u55) |
| 477 | +@common.XfailIfNoCorstone300 |
| 478 | +def test_upsample_nearest2d_vec_u55_INT_Interpolate(test_data: torch.Tensor): |
| 479 | + test_data, size, scale_factor, compare_outputs = test_data() |
| 480 | + pipeline = EthosU55PipelineINT[input_t1]( |
| 481 | + Interpolate(size, scale_factor), |
| 482 | + (test_data,), |
| 483 | + aten_op, |
| 484 | + exir_op, |
| 485 | + ) |
463 | 486 | pipeline.run() |
464 | 487 |
|
465 | 488 |
|
466 | 489 | @common.parametrize("test_data", test_data_u55) |
467 | 490 | @common.XfailIfNoCorstone300 |
468 | | -def test_upsample_nearest2d_vec_u55_INT_Interpolate_not_delegated( |
| 491 | +def test_upsample_nearest2d_vec_u55_INT_UpsamplingNearest2d( |
469 | 492 | test_data: torch.Tensor, |
470 | 493 | ): |
471 | 494 | test_data, size, scale_factor, compare_outputs = test_data() |
| 495 | + pipeline = EthosU55PipelineINT[input_t1]( |
| 496 | + UpsamplingNearest2d(size, scale_factor), |
| 497 | + (test_data,), |
| 498 | + aten_op, |
| 499 | + exir_op, |
| 500 | + ) |
| 501 | + pipeline.run() |
| 502 | + |
| 503 | + |
| 504 | +def test_upsample_nearest2d_vec_u55_INT_unsupported_scale_not_delegated(): |
| 505 | + # 2.25 rounds a 2x2 input to 4x4, which looks like a supported 2x resize from shapes alone. |
| 506 | + test_data = torch.rand(1, 4, 2, 2) |
472 | 507 | pipeline = OpNotSupportedPipeline[input_t1]( |
473 | | - Interpolate(size, scale_factor), |
| 508 | + Interpolate(None, 2.25), |
474 | 509 | (test_data,), |
475 | 510 | {exir_op: 1}, |
476 | 511 | n_expected_delegates=0, |
477 | 512 | quantize=True, |
478 | 513 | u55_subset=True, |
479 | 514 | ) |
480 | | - |
481 | 515 | pipeline.run() |
482 | 516 |
|
483 | 517 |
|
484 | | -@common.parametrize("test_data", test_data_u55) |
485 | | -@common.XfailIfNoCorstone300 |
486 | | -def test_upsample_nearest2d_vec_u55_INT_UpsamplingBilinear2d_not_delegated( |
487 | | - test_data: torch.Tensor, |
488 | | -): |
489 | | - test_data, size, scale_factor, compare_outputs = test_data() |
| 518 | +def test_upsample_nearest2d_vec_u55_INT_unsupported_batch_not_delegated(): |
| 519 | + test_data = torch.rand(2, 4, 8, 3) |
490 | 520 | pipeline = OpNotSupportedPipeline[input_t1]( |
491 | | - UpsamplingNearest2d(size, scale_factor), |
| 521 | + Interpolate(None, 2.0), |
492 | 522 | (test_data,), |
493 | 523 | {exir_op: 1}, |
494 | 524 | n_expected_delegates=0, |
495 | 525 | quantize=True, |
496 | 526 | u55_subset=True, |
497 | 527 | ) |
498 | | - |
499 | 528 | pipeline.run() |
500 | 529 |
|
501 | 530 |
|
| 531 | +def test_upsample_nearest2d_vec_u55_INT_dynamic_batch_not_delegated(): |
| 532 | + test_data = torch.rand(2, 4, 8, 3) |
| 533 | + batch = torch.export.Dim("batch", min=1, max=4) |
| 534 | + tester = ArmTester( |
| 535 | + Interpolate(None, 2.0), |
| 536 | + (test_data,), |
| 537 | + common.get_u55_compile_spec(), |
| 538 | + dynamic_shapes={"x": {0: batch}}, |
| 539 | + ) |
| 540 | + tester.quantize().export().to_edge().partition() |
| 541 | + |
| 542 | + targets = { |
| 543 | + node.target |
| 544 | + for node in tester.stages[tester.cur].artifact.exported_program().graph.nodes |
| 545 | + } |
| 546 | + assert exir_ops.edge.aten.upsample_nearest2d.vec in targets |
| 547 | + assert torch.ops.higher_order.executorch_call_delegate not in targets |
| 548 | + |
| 549 | + |
| 550 | +def test_upsample_nearest2d_vec_u55_INT_dynamic_spatial_size_not_delegated(): |
| 551 | + test_data = torch.rand(1, 4, 8, 3) |
| 552 | + input_height = torch.export.Dim("input_height", min=4, max=12) |
| 553 | + input_width = torch.export.Dim("input_width", min=2, max=6) |
| 554 | + tester = ArmTester( |
| 555 | + Interpolate((16, 6), None), |
| 556 | + (test_data,), |
| 557 | + common.get_u55_compile_spec(), |
| 558 | + dynamic_shapes={"x": {2: input_height, 3: input_width}}, |
| 559 | + ) |
| 560 | + tester.quantize().export().to_edge() |
| 561 | + resize_node = next( |
| 562 | + node |
| 563 | + for node in tester.stages[tester.cur].artifact.exported_program().graph.nodes |
| 564 | + if node.target == exir_ops.edge.aten.upsample_nearest2d.vec |
| 565 | + ) |
| 566 | + assert not EthosU55ResizeCheck(WhyNoPartitionReporter()).is_node_supported( |
| 567 | + {}, resize_node |
| 568 | + ) |
| 569 | + |
| 570 | + tester.partition() |
| 571 | + targets = { |
| 572 | + node.target |
| 573 | + for node in tester.stages[tester.cur].artifact.exported_program().graph.nodes |
| 574 | + } |
| 575 | + assert exir_ops.edge.aten.upsample_nearest2d.vec in targets |
| 576 | + assert torch.ops.higher_order.executorch_call_delegate not in targets |
| 577 | + |
| 578 | + |
502 | 579 | @common.parametrize("test_data", test_data_suite_dynamic) |
503 | 580 | def test_upsample_nearest2d_vec_tosa_FP_dynamic_nearest(test_data: torch.Tensor): |
504 | 581 | test_data, size, scale_factor, compare_outputs = test_data() |
|
0 commit comments