Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3e57eea

Browse files
committed
[jit] add docs for serialization
ghstack-source-id:7743b42Pull Requestresolved:#23456
1 parent0dcb875 commit3e57eea

File tree

2 files changed

+197
-232
lines changed

2 files changed

+197
-232
lines changed

‎torch/csrc/jit/README.md‎

Lines changed: 6 additions & 232 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,20 +1146,20 @@ The intention is that if you only mutate the graph through `AliasDb`, you don't
11461146
TODO: differentiation, symbolic autograd,
11471147
TODO: fusion, operators
11481148

1149-
#Profiling Programs
1149+
#Profiling Programs
11501150

1151-
`prim::profile` nodes are inserted on every**use** of a value by`ProfilingRecord::instrumentBlock`. Every`prim::profile` node runs a lambda that uses a captured, initial type value and the type of an incoming tensor and merges the two into`ProfiledTensorType`
1151+
`prim::profile` nodes are inserted on every**use** of a value by`ProfilingRecord::instrumentBlock`. Every`prim::profile` node runs a lambda that uses a captured, initial type value and the type of an incoming tensor and merges the two into`ProfiledTensorType`
11521152

11531153
`prim::profile` nodes are replaced with`prim::Guard` nodes by`InsertGuards`.`prim::Guard` nodes are inserted to guarantee that beyond the guard a guarded tensor will always be of the profiled shape. This guarantee will enable optimizations and codegens to generate more efficient code.
11541154

1155-
JIT attempts to reduce the number of`prim::Guard` nodes as these nodes may interefere with optimizations.
1156-
* First,`GuardElimination::moveGuardsToDefs` tries to move`prim::Guards` to their definitions, so the guards guarding the same tensor follow the definition directly or another guard on the same tensor. This step is done in
1157-
* This ordering allows us to**coalesce** (done in`GuardElimination::coalesceGuards`) multiple guards into a single one.
1155+
JIT attempts to reduce the number of`prim::Guard` nodes as these nodes may interefere with optimizations.
1156+
* First,`GuardElimination::moveGuardsToDefs` tries to move`prim::Guards` to their definitions, so the guards guarding the same tensor follow the definition directly or another guard on the same tensor. This step is done in
1157+
* This ordering allows us to**coalesce** (done in`GuardElimination::coalesceGuards`) multiple guards into a single one.
11581158
* After guards are**coaslesced** ,`GuardElimination::eliminateGuards` attempts to eliminate more guards as follows: it inspects each operation and its inputs. It checks if inputs to the operation are guarded and also if the operation produces the consistent shapes given the guarded inputs. For example, if two inputs to`add` are guaranteed to be of shape`(2, 3)`, the output shape will also always be`(2, 3)` If this property holds, JIT is allowed to remove the guard guarding operation's output.
11591159

11601160
Lastly, JIT needs to be handle cases when the assumptions about tensor shapes fail at runtime. To handle guard failures, JIT needs to be able to run the original code i.e. the code that doesn't rely on assumptions about shapes. As guards can be inserted and moved (by Optimizer) at/to arbitrary points in a computional graph, JIT needs to be able to resume execution starting from those arbitrary points onward.
11611161

1162-
`InsertBailoutNodes` builds deoptimized versions of the original computational graph, that contain the rest of computations starting from their corresponding guard failure poins and, also, captures live values needed to execute those deoptimized graphs. In other words, the pass replaces`prim::Guard` nodes with`prim::BailOut` nodes which have the`attr::Subgraph` attributes set to the deoptimized versions of the remaining computations at their corresponding`prim::Guard`s.
1162+
`InsertBailoutNodes` builds deoptimized versions of the original computational graph, that contain the rest of computations starting from their corresponding guard failure poins and, also, captures live values needed to execute those deoptimized graphs. In other words, the pass replaces`prim::Guard` nodes with`prim::BailOut` nodes which have the`attr::Subgraph` attributes set to the deoptimized versions of the remaining computations at their corresponding`prim::Guard`s.
11631163

11641164
#Saving Programs
11651165

@@ -1247,232 +1247,6 @@ def forward(self,
12471247
return x0
12481248
```
12491249

1250-
##Serialization
1251-
1252-
[export.cpp](export.cpp)
1253-
[pickler.cpp](pickler.cpp)
1254-
[import.cpp](import.cpp)
1255-
[caffe2/proto/torch.proto](../../../caffe2/proto/torch.proto)
1256-
1257-
1258-
TorchScript programs are serialized with a call to`torch.jit.save()`. The resulting file (ending in`.pt` by convention) can be loaded/executed in C++ and Python.
1259-
1260-
###Overview
1261-
1262-
The`.pt` file is a zip archive (which can be opened with tools such as`unzip`) and contains:
1263-
* code - the Python printed graph of a module
1264-
*`model.json` - a JSON file of a model Protobuf def (defined in[torch.proto](caffe2/proto/torch.proto))
1265-
*`tensors/` - each of the tensors of the model, with their tensor storage stored directly in a file
1266-
*`attributes.pkl` - a Python`pickle` archive of the attributes of a module
1267-
1268-
###`model.json`
1269-
The`model.json` contains the structure information of the model. Each model must contain one main Module, and each module may contain multiple submodules, and each module contains a bunch of parameters (tensors). We serialize the metadata for each tensor inline in`model.json` (e.g., dims, strides, record name, etc).
1270-
1271-
###`code/`
1272-
1273-
The`code` directory contains the Python Printed`Graph`s of the main module and its submodules.
1274-
1275-
###`tensors/`
1276-
1277-
During export a list of all the tensors in a model is created. Tensors can come from either module parameters or Tensor type attributes. Metadata about each tensor is stored in`model.json` with an index into this list. The`data` field refers to the file which contains the tensor storage data. Tensors are saved by directly writing the Tensor storage to a file.
1278-
1279-
`model.json`
1280-
```json
1281-
{
1282-
...
1283-
"tensors": [
1284-
{
1285-
"dims": [
1286-
"40",
1287-
"800"
1288-
],
1289-
"offset":"0",
1290-
"strides": [
1291-
"800",
1292-
"1"
1293-
],
1294-
"requiresGrad":true,
1295-
"dataType":"FLOAT",
1296-
"data": {
1297-
"key":"tensors/0"
1298-
},
1299-
"device":"cpu"
1300-
}
1301-
],
1302-
...
1303-
}
1304-
```
1305-
1306-
###`attributes.pkl`
1307-
1308-
[pickler.h](pickler.h),
1309-
[pickler.cpp](pickler.cpp),
1310-
[torch/jit/_pickle.py](../../../torch/jit/_pickle.py)
1311-
[caffe2/proto/torch.proto](../../../caffe2/proto/torch.proto)
1312-
1313-
Attributes are all module properties that are not parameters or constants. Attributes are saved in a list in the order they were defined on the module. A given module may have many attributes of different types and many submodules, each with their own attributes. Attribute metadata is recorded in`model.json`:
1314-
*`type` - the full type of the attribute (in[Mypy syntax](https://mypy.readthedocs.io/en/latest/cheat_sheet_py3.html))
1315-
*`name` - the attribute's name
1316-
*`id` - the offset into the saved list of all model attributes
1317-
1318-
In`model.json`:
1319-
```json
1320-
{
1321-
"mainModule": {
1322-
"submodules": [
1323-
{
1324-
...
1325-
"attributes": [
1326-
{
1327-
"type":"Dict[str, str]",
1328-
"name":"my_submodule_dictionary",
1329-
"id":0
1330-
},
1331-
{
1332-
"type":"List[Tuple[int, int]]",
1333-
"name":"my_submodule_list",
1334-
"id":1
1335-
}
1336-
]
1337-
...
1338-
},
1339-
...
1340-
],
1341-
...
1342-
"attributes": [
1343-
{
1344-
"type":"Dict[str, str]",
1345-
"name":"my_main_module_dictionary",
1346-
"id":2
1347-
},
1348-
{
1349-
"type":"Tensor",
1350-
"name":"my_main_module_tensor",
1351-
"id":3
1352-
}
1353-
]
1354-
...
1355-
},
1356-
}
1357-
```
1358-
1359-
Attributes of the main module and its submodules are saved to a single file in the`zip` archive of a`.pt` file named`attributes.pkl`. Attributes are stored as a Python`pickle` archive.`pickle`'s format was chosen due to:
1360-
***user friendliness** - the attributes file can be loaded in Python with`pickle`
1361-
***size limits** - formats such as Protobuf empose size limits on total message size, whereas pickle limits are on individual values (e.g. strings cannot be longer than 4 GB)
1362-
***standard format** -`pickle` is a standard Python module with a reasonably simple format. The format is a program to be consumed by a stack machine that is detailed in Python's[`pickletools.py`](https://svn.python.org/projects/python/trunk/Lib/pickletools.py)
1363-
***built-in memoization** - for shared reference types (e.g. Tensor, string, lists, dicts)
1364-
***self describing** - a separate definition file is not needed to understand the pickled data
1365-
***eager mode save** -`torch.save()` already produces a`pickle` archive, so doing the same with attributes avoids introducing yet another format
1366-
1367-
[pickler.cpp](pickler.cpp) implements a subset of the Pickle format necessary for TorchScript models.
1368-
1369-
1370-
A single file is used for the top level module and all submodules so that attributes can reference each other and share values. Unpickling`attributes.pkl` will return a tuple of values corresponding to the attributes.
1371-
1372-
All attributes are written into the`attributes.pkl` file with the exception of tensors, which store only a tensor table index (see "tensors" above). PyTorch functions defined in[torch/jit/_pickle.py](../../../torch/jit/_pickle.py) are used to mark special data types, such as this tensor table index or specialized lists. To load the`attributes.pkl` file, use the`pickle` module in Python:
1373-
1374-
```python
1375-
import pickle
1376-
# attributes.pkl include references to functions in torch.jit._pickle
1377-
import torch
1378-
1379-
pickle.load(open("attributes.pkl","rb"))
1380-
```
1381-
1382-
If for some reason you don't have PyTorch installed, you can still load`attributes.pkl` with a custom[`Unpickler`](https://docs.python.org/3/library/pickle.html#pickle.Unpickler):
1383-
1384-
```python
1385-
import pickle
1386-
1387-
classJitUnpickler(pickle.Unpickler):
1388-
deffind_class(self,module,name):
1389-
if module!='torch.jit._pickle':
1390-
raiseRuntimeError("Unknown module")
1391-
1392-
identity=lambdax: x
1393-
if name=='build_tensor_from_id':
1394-
# Without the tensor table we can't do anything other than
1395-
# return the tensor ID
1396-
return identity
1397-
elif name=='build_intlist':
1398-
return identity
1399-
1400-
print(JitUnpickler(open("out_dir/out/attributes.pkl","rb")).load())
1401-
```
1402-
1403-
####Binary Format
1404-
1405-
Running the following snippet produces a`ScriptModule` with several attributes.
1406-
Python's`pickletools` module can be used to decode the binary blob of`attributes.pkl` into a human readable format.
1407-
1408-
```python
1409-
import pickletools
1410-
import zipfile
1411-
import torch
1412-
from typingimport Tuple, List
1413-
1414-
classM(torch.jit.ScriptModule):
1415-
def__init__(self):
1416-
super(M,self).__init__()
1417-
self.float= torch.jit.Attribute(2.3,float)
1418-
self.tuple= torch.jit.Attribute((1,2,3,4), Tuple[int,int,int,int])
1419-
self.tensor= torch.jit.Attribute(torch.randn(2,2), torch.Tensor)
1420-
self.int_list= torch.jit.Attribute([1,2,3,4], List[int])
1421-
1422-
@torch.jit.script_method
1423-
defforward(self):
1424-
return (self.float,self.tuple,self.tensor,self.int_list)
1425-
1426-
M().save("out.zip")
1427-
model_zip= zipfile.ZipFile("out.zip",'r')
1428-
model_zip.extractall("out_dir")
1429-
pickletools.dis(open("out_dir/out/attributes.pkl","rb"))
1430-
```
1431-
1432-
1433-
The output of the above commands demonstrates the concepts described earlier. Attributes are wrapped in with`2: EMPTY_LIST` and appear in the order they are defined on the module. Functions for certain special types (e.g.`List[int]`,`Tensor`) can be seen at`37: GLOBAL` and`66: GLOBAL`, followed by data specific to that type, then finally by an instruction to build the object at`65: BUILD` and`113: BUILD` respectively.
1434-
```
1435-
0: \x80 PROTO 2
1436-
2: ( MARK
1437-
3: G BINFLOAT 2.3
1438-
12: ( MARK
1439-
13: K BININT1 1
1440-
15: K BININT1 2
1441-
17: K BININT1 3
1442-
19: K BININT1 4
1443-
21: t TUPLE (MARK at 12)
1444-
22: q BINPUT 0
1445-
24: c GLOBAL 'torch.jit._pickle build_tensor_from_id'
1446-
64: q BINPUT 1
1447-
66: ( MARK
1448-
67: K BININT1 0
1449-
69: t TUPLE (MARK at 66)
1450-
70: R REDUCE
1451-
71: c GLOBAL 'torch.jit._pickle build_intlist'
1452-
104: q BINPUT 2
1453-
106: ( MARK
1454-
107: ] EMPTY_LIST
1455-
108: ( MARK
1456-
109: K BININT1 1
1457-
111: K BININT1 2
1458-
113: K BININT1 3
1459-
115: K BININT1 4
1460-
117: e APPENDS (MARK at 108)
1461-
118: t TUPLE (MARK at 106)
1462-
119: R REDUCE
1463-
120: q BINPUT 3
1464-
122: t TUPLE (MARK at 2)
1465-
123: . STOP
1466-
highest protocol among opcodes = 2
1467-
```
1468-
1469-
1470-
1471-
###Implementation Details
1472-
1473-
[export.cpp](export.cpp) and[import.cpp](import.cpp) handle producing the proper protobuf definitions and (de)serializing tensor data. They use[pickler.h](pickler.cpp) which implements a subset of the`pickle` stack machine.
1474-
1475-
14761250
#Python Bindings
14771251

14781252
TODO: Script Module, torch.jit.trace,__constant__ handling, weak script modules

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp