You signed in with another tab or window.Reload to refresh your session.You signed out in another tab or window.Reload to refresh your session.You switched accounts on another tab or window.Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: torch/csrc/jit/README.md
+6-232Lines changed: 6 additions & 232 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1146,20 +1146,20 @@ The intention is that if you only mutate the graph through `AliasDb`, you don't
1146
1146
TODO: differentiation, symbolic autograd,
1147
1147
TODO: fusion, operators
1148
1148
1149
-
#Profiling Programs
1149
+
#Profiling Programs
1150
1150
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`
1152
1152
1153
1153
`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.
1154
1154
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.
1158
1158
* 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.
1159
1159
1160
1160
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.
1161
1161
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.
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.
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)
***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
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.