Commit 89809c4
authored
Restore program segments from a view of the input (pytorch#23340)
## What is wrong today
`deserialize_pte_binary` reads a `.pte` file back into a Python
`Program`. Large data, such as delegate payloads and constant tensors,
is stored in segments at the end of the file.
To restore them, it first takes everything after the program data as a
new `bytes` object, then cuts each segment out of that. Slicing `bytes`
makes a copy, so while it runs the process holds:
1. the input data,
2. a copy of all the segments together,
3. a second copy of each segment as it is restored.
For a program with several large segments, for example a delegate plus
its constants, that is gigabytes of extra memory just to read the file.
## What this change does
`deserialize_pte_binary` passes a `memoryview` of the input to
`_restore_segments` instead of a sliced copy. A `memoryview` slice
points at the same memory and copies nothing.
```python
return _restore_segments(
program=program,
segment_data=memoryview(program_data)[segment_base_offset:],
)
```
`_restore_segments` still copies each segment into its own `bytes`, so:
- the restored program carries the same types as before (`bytes` in
delegate data, constant buffers and named data),
- nothing in the result keeps the whole input alive.
Each segment is now copied once instead of twice. The output does not
change.
When a file has only one segment and it runs to the end of the file,
Python does not copy a slice that covers the whole object, so main made
only one copy there too, and this change saves nothing. It helps every
program with more than one segment, for example a delegate plus
constants, or several delegates.
## What was tested
- New unit test in `exir/_serialize/test/test_program.py`:
`_restore_segments` receives a `memoryview` whose underlying object is
the input itself, and the restored delegate data is `bytes` equal to the
original blob. It fails before this change (it receives a `bytes` copy)
and passes after it.
- The rest of `test_program.py` and
`backends/cuda/tests/test_merge_ptes.py` (which reads merged programs
back with this function) pass before and after.
- Read back a 2 GiB program with two 1 GiB delegate segments on Linux
aarch64. Peak memory added by `deserialize_pte_binary` fell from 4.0 GiB
to 2.0 GiB, and the restored delegates were identical.1 parent adfd1d7 commit 89809c4
2 files changed
Lines changed: 36 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
670 | 670 | | |
671 | 671 | | |
672 | 672 | | |
673 | | - | |
| 673 | + | |
674 | 674 | | |
675 | 675 | | |
676 | 676 | | |
| |||
693 | 693 | | |
694 | 694 | | |
695 | 695 | | |
696 | | - | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
697 | 699 | | |
698 | 700 | | |
699 | 701 | | |
| |||
754 | 756 | | |
755 | 757 | | |
756 | 758 | | |
757 | | - | |
| 759 | + | |
| 760 | + | |
758 | 761 | | |
759 | | - | |
| 762 | + | |
| 763 | + | |
760 | 764 | | |
761 | 765 | | |
762 | 766 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| 27 | + | |
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
| |||
749 | 751 | | |
750 | 752 | | |
751 | 753 | | |
| 754 | + | |
| 755 | + | |
| 756 | + | |
| 757 | + | |
| 758 | + | |
| 759 | + | |
| 760 | + | |
| 761 | + | |
| 762 | + | |
| 763 | + | |
| 764 | + | |
| 765 | + | |
| 766 | + | |
| 767 | + | |
| 768 | + | |
| 769 | + | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
752 | 780 | | |
753 | 781 | | |
754 | 782 | | |
| |||
0 commit comments