Skip to content
This repository was archived by the owner on Jul 10, 2025. It is now read-only.

Commit 8f0de6e

Browse files
author
ematejska
authored
Merge pull request #285 from abattery/master
RFC: Builtin code extension in TFLite
2 parents 9b7c014 + 4f18e41 commit 8f0de6e

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Builtin operator code extension in TensorFlow Lite
2+
3+
Status | Accepted
4+
:------------ | :----------------------------------
5+
**Author(s)** | Jae sung Chung ([email protected])
6+
**Sponsor** | Jared Duke ([email protected])
7+
**Updated** | 2020-09-01
8+
9+
## Objective
10+
11+
This RFC proposes a FlatBuffer schema change in TensorFlow Lite, which extends
12+
the builtin operator code in the `OperatorCode` table section to resolve the
13+
shortage problem in the builtin operator code. Even though Flatbuffer is an
14+
internal details of the TensorFlow Lite, some advanced users, who write
15+
visualization tools or third-party delegates, depend on reading Flatbuffer
16+
schema directly via C++ API. This RFC focuses on the solution for the shortage
17+
problem and its compatibility issues.
18+
19+
### Goals:
20+
21+
* Discuss how to resolve the builtin operator code shortage problem in
22+
TensorFlow Lite Flatbuffer schema without breaking backward-compatibility of
23+
the existing TensorFlow Lite Flatbuffer schema version 3 files in future
24+
versions of the TensorFlow Lite library.
25+
26+
## Background
27+
28+
A byte type is used for builtin operator code in Flatbuffer, so only 127 builtin
29+
operators can be added. TensorFlow Lite builtin operator library already reached
30+
126 operators.
31+
32+
```
33+
enum BuiltinOperator : byte {
34+
...
35+
}
36+
```
37+
38+
TensorFlow Lite keeps extending to support more domains in ML and users require
39+
more builtin operators to increase ML model coverage on device, for example Hash
40+
table support and so on.
41+
42+
### Compatibility issues
43+
44+
TensorFlow Lite has used its Flatbuffer schema version 3 since 2018 and a lot of
45+
TensorFlow Lite models can be found over the TensorFlow project sites.
46+
Supporting the schema version 3 is critical for future versions of TensorFlow
47+
Lite.
48+
49+
The compatibility issue of newly generated models, that will contain new builtin
50+
operators after this proposal's change, from old TensorFlow Lite libraries won't
51+
be a problem because the TensorFlow Lite library's version always should be the
52+
same or the newer than the TensorFlow Lite Converter API's version for builtin
53+
operator availability.
54+
55+
## Proposal
56+
57+
### Schema changes
58+
59+
For resolving compatibility issues easily, the old builtin operator code will
60+
remain and the new builtin operator code will be added into the last position as
61+
follows.
62+
63+
```
64+
enum BuiltinOperator : int32 {
65+
... // Existing builtin operator codes
66+
PLACEHOLDER_FOR_GREATER_OP_CODES = 127,
67+
// New builtin operators will be added in here.
68+
BROADCAST_TO = 128
69+
}
70+
71+
// An OperatorCode can be an enum value (BuiltinOperator) if the operator is a
72+
// builtin, or a string if the operator is custom.
73+
table OperatorCode {
74+
// This field is for backward compatibility. This field will be used when
75+
// the value of the extended builtin_code field has less than
76+
// BulitinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
77+
deprecated_builtin_code:byte;
78+
custom_code:string;
79+
80+
// The version of the operator. The version need to be bumped whenever new
81+
// parameters are introduced into an op.
82+
version:int = 1;
83+
84+
// This field is introduced for resolving op builtin operator code shortage problem
85+
// (the original BuiltinOperator enum field was represented as a byte).
86+
// This field will be used when the value of the extended builtin_code field
87+
// is greater than BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES.
88+
builtin_code:BuiltinOperator;
89+
}
90+
91+
```
92+
93+
### How to Read `builtin_code`
94+
95+
The builtin operator code value will co-exist in the two fields. Old schema
96+
version 3 models will have the default value in the new field. For those old
97+
schema models, the `deprecated_builtin_code` field should be read when the
98+
default value is set in the new `builtin_code` field.
99+
100+
```
101+
BuiltinOperator builtin_code = (op_code->builtin_code ? op_code->builtin_code
102+
: static_cast<BuiltinOperator>(op_code->deprecated_builtin_code));
103+
```
104+
105+
#### Handling compatibility issues
106+
107+
| | Old .tflite model | New .tflite model |
108+
| ------------------ | ---------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
109+
| Old TFLite runtime | OK<br>(Current behavior) | OK<br>(As long as the model is not using<br>any *new* builtin ops. If it is, it will<br>fail as it would when using any<br> other unsupported op.) |
110+
| New TFLite runtime | OK<br>(Uses the legacy builtin op field) | OK<br>(Uses the new builtin op field) |
111+
112+
The details will be described in the following sections.
113+
114+
##### Supporting schema version 3 models
115+
116+
The TensorFlow Lite library built after the proposal will read the existing
117+
`deprecated_builtin_code` field from old model files.
118+
119+
The new `builtin_code` field is not available in the version 3 models. Flatbuffer
120+
library will feed zero value, which is the default value in the version 3a schema. The
121+
actual builtin operator code value will exist in the deprecated, renamed
122+
`deprecated_builtin_code` field.
123+
124+
##### Compatibility with old TensorFlow Lite libraries
125+
126+
The TensorFlow Lite library built before the proposal will read the existing
127+
`deprecated_builtin_code` field. However, it will not handle new operations
128+
declared above 127. This is intended behavior, as it doesn't have a definition
129+
for the higher op values anyway.
130+
131+
### Schema version
132+
133+
Schema version will remain as before since we are not going to break backward
134+
compatibility in the schema level. However, in the viewpoint of the Flatbuffer
135+
tool, renaming a field is treated as compatibility breakage even though the
136+
runtime code could handle schema formats before and after both. The schema
137+
change can be regarded as a minor version. The schema version "3a" can be an
138+
option.
139+
140+
### New utils for schema manipulation
141+
142+
After the proposal is landed, the codes, that read builtin operator code from
143+
TensorFlow Lite Flatbuffer, requires accessing both `builtin_code` and
144+
`deprecated_builtin_code` fields.
145+
146+
To avoid redundant logics in a lot of places, the RFC proposes the following
147+
helper functions in the new C++ library, `tensorflow/lite/schema:schema_utils`.
148+
149+
```
150+
BuiltinOperator GetBuiltinCode(const OperatorCode *op_code);
151+
BuiltinOperator GetBuiltinCode(const OperatorCodeT *op_code);
152+
```
153+
154+
The above library also provides the following `OperatorCode` table object
155+
creation methods for backward compatibility.
156+
157+
These are manually copied from the flatbuffer generated code from schema version 3.
158+
They serve as overloads for the version 3a's CreateOperatorCode functions in
159+
schema_generated.h and enable code that still assumes flatbuffer schema version 3 to be
160+
unchanged with the inclusion of the schema_utils header.
161+
162+
```
163+
flatbuffersf:Offset<OperatorCode> CreateOperatorCode(
164+
flatbuffers::FlatBufferBuilder &_fbb,
165+
tflite::BuiltinOperator builtin_code = tflite::BuiltinOperator_ADD,
166+
flatbuffers::Offset<flatbuffers::String> custom_code = 0,
167+
int32_t version = 1);
168+
169+
flatbuffers::Offset<OperatorCode> CreateOperatorCodeDirect(
170+
flatbuffers::FlatBufferBuilder &_fbb,
171+
tflite::BuiltinOperator builtin_code = tflite::BuiltinOperator_ADD,
172+
const char *custom_code = nullptr, int32_t version = 1);
173+
```

0 commit comments

Comments
 (0)