aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/contrib/lite/g3doc/custom_operators.md
diff options
context:
space:
mode:
Diffstat (limited to 'tensorflow/contrib/lite/g3doc/custom_operators.md')
-rw-r--r--tensorflow/contrib/lite/g3doc/custom_operators.md83
1 files changed, 83 insertions, 0 deletions
diff --git a/tensorflow/contrib/lite/g3doc/custom_operators.md b/tensorflow/contrib/lite/g3doc/custom_operators.md
index 972e57f73e..d979353bb3 100644
--- a/tensorflow/contrib/lite/g3doc/custom_operators.md
+++ b/tensorflow/contrib/lite/g3doc/custom_operators.md
@@ -1,3 +1,6 @@
+book_path: /mobile/_book.yaml
+project_path: /mobile/_project.yaml
+
# How to use custom operators
TensorFlow Lite currently supports a subset of TensorFlow operators. However, it
@@ -89,3 +92,83 @@ builtins.AddCustom("Sin", Register_SIN());
Note that a similar process as above can be followed for supporting for a set of
operations instead of a single operator.
+
+## Best Practices for writing custom operators
+
+1. Optimize memory allocations and de-allocations cautiously. It is more
+ efficient to allocate memory in Prepare() instead of Invoke(), and allocate
+ memory before a loop instead of in every iteration. Use temporary tensors
+ data rather than mallocing yourself (see item 2). Use pointers/references
+ instead of copying as much as possible.
+
+2. If a data structure will persist during the entire operation, we advise
+ pre-allocating the memory using temporary tensors. You may need to use
+ OpData struct to reference the tensor indices in other functions. See
+ example in the
+ [kernel for convolution](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/kernels/conv.cc).
+ A sample code snippet is below
+
+ ```
+ auto* op_data = reinterpret_cast<OpData*>(node->user_data);
+ TfLiteIntArrayFree(node->temporaries);
+ node->temporaries = TfLiteIntArrayCreate(1);
+ node->temporaries->data[0] = op_data->temp_tensor_index;
+ TfLiteTensor* temp_tensor = &context->tensors[op_data->temp_tensor_index];
+ temp_tensor->type = kTfLiteFloat32;
+ temp_tensor->allocation_type = kTfLiteArenaRw;
+ ```
+
+3. If it doesn't cost too much wasted memory, prefer using a static fixed size
+ array (or in Resize() pre-allocated std::vector) rather than using a
+ dynamically allocating std::vector every iteration of execution.
+
+4. Avoid instantiating standard library container templates that don't already
+ exist, because they affect binary size. For example, if you need a std::map
+ in your operation that doesn't exist in other kernels, using a std::vector
+ with direct indexing mapping could work while keeping the binary size small.
+ See what other kernels use to gain insight (or ask).
+
+5. Check the pointer to the memory returned by malloc. If this pointer is
+ nullptr, no operations should be performed using that pointer. If you
+ malloc() in a function and have an error exit, deallocate memory before you
+ exit.
+
+6. Use TF_LITE_ENSURE(context, condition) to check for a specific condition.
+ Your code must not leave memory hanging when TF_LITE_ENSURE is done, i.e.,
+ these should be done before any resources are allocated that will leak.
+
+## Special TF Graph Attributes
+
+When Toco convertes a TF graph into TFLite format, it makes some assumption
+about custom operations that might be not correct. In this case, the generated
+graph can be not executable.
+
+It is possible to add aditional information about your custom op output to TF
+graph before it is converted. The following attributes are supported:
+
+- **_output_quantized** a boolean attribute, true if the operation outputs are
+ quantized
+- **_output_types** a list of types for output tensors
+- **_output_shapes** a list of shapes for output tensors
+
+### Setting the Attributes
+
+This is an example how the attributes can be set:
+
+```python
+frozen_graph_def = tf.graph_util.convert_variables_to_constants(...)
+for node in frozen_graph_def.node:
+ if node.op == 'sin':
+ node.attr['_output_types'].list.type.extend([
+ types_pb2.DT_FLOAT,
+ ])
+ node.attr['_output_shapes'].list.shape.extend([
+ tf.TensorShape([10]),
+ ])
+ node.attr['_output_quantized'].b = False
+tflite_model = tf.contrib.lite.toco_convert(
+ frozen_graph_def,...)
+```
+
+**Note:** After the attributes are set, the graph can not be executed by
+Tensorflow, therefore it should be done just before the conversion.