Create a simple PIP package generator for standalone TF Lite.

Based on original dkovalev@

PiperOrigin-RevId: 221543483
This commit is contained in:
Andrew Selle 2018-11-14 17:30:43 -08:00 committed by TensorFlower Gardener
parent 6f99a8181d
commit 5847293aeb
5 changed files with 241 additions and 0 deletions

View File

@ -208,6 +208,9 @@ $(BENCHMARK_BINARY) : $(BENCHMARK_LIB)
benchmark: $(BENCHMARK_BINARY)
libdir:
@echo $(LIBDIR)
# Gets rid of all generated files.
clean:
rm -rf $(MAKEFILE_DIR)/gen

View File

@ -0,0 +1 @@
recursive-include * *.py

View File

@ -0,0 +1,33 @@
# Building TensorFlow Lite Standalone Pip
Many users would like to deploy TensorFlow lite interpreter and use it from
Python without requiring the rest of TensorFlow.
## Steps
To build a binary wheel run this script:
```
sudo apt install swig libjpeg-dev zlib1g-dev python3-dev python3-numpy
sh tensorflow/lite/tools/pip_package/build_pip_package.sh
```
That will print out some output and a .whl file. You can then install that
```
pip install --upgrade <wheel>
```
Note, unlike tensorflow this will be installed to a tflite_runtime namespace.
You can then use the Tensorflow Lite interpreter as.
```
import tflite_runtime as tflr
interpreter = tflr.lite.Interpreter(model_path="foo.tflite")
```
This currently works to build on Linux machines including Raspberry Pi. In
the future, cross compilation to smaller SOCs like Raspberry Pi from
bigger host will be supported.
## Caveats
* You cannot use TensorFlow Select ops, only TensorFlow Lite builtins.
* Currently custom ops and delegates cannot be registered.

View File

@ -0,0 +1,54 @@
#!/usr/bin/env bash
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
set -e
# Find where this script lives and then the Tensorflow root.
MY_DIRECTORY=`dirname $0`
export TENSORFLOW_SRC_ROOT=`realpath $MY_DIRECTORY/../../../..`
export TENSORFLOW_VERSION=`grep "_VERSION = " $TENSORFLOW_SRC_ROOT/tensorflow/tools/pip_package/setup.py | cut -d'=' -f 2 | sed "s/[ '-]//g"`;
# Build a pip build tree.
BUILD_ROOT=/tmp/tflite_pip
rm -rf $BUILD_ROOT
mkdir -p $BUILD_ROOT/tflite_runtime/lite
mkdir -p $BUILD_ROOT/tflite_runtime/lite/python
# Build an importable module tree
cat > $BUILD_ROOT/tflite_runtime/__init__.py <<EOF;
import tflite_runtime.lite.interpreter
EOF
cat > $BUILD_ROOT/tflite_runtime/lite/__init__.py <<EOF;
from interpreter import Interpreter as Interpreter
EOF
cat > $BUILD_ROOT/tflite_runtime/lite/python/__init__.py <<EOF;
# Python module for TensorFlow Lite
EOF
# Copy necessary source files
TFLITE_ROOT=$TENSORFLOW_SRC_ROOT/tensorflow/lite
cp -r $TFLITE_ROOT/python/interpreter_wrapper $BUILD_ROOT
cp $TFLITE_ROOT/python/interpreter.py $BUILD_ROOT/tflite_runtime/lite/
cp $TFLITE_ROOT/tools/pip_package/setup.py $BUILD_ROOT
cp $TFLITE_ROOT/tools/pip_package/MANIFEST.in $BUILD_ROOT
# Build the Pip
cd $BUILD_ROOT
python setup.py bdist_wheel

View File

@ -0,0 +1,150 @@
# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""TensorFlow Lite is for mobile and embedded devices.
TensorFlow Lite is the official solution for running machine learning models on
mobile and embedded devices. It enables on-device machine learning inference
with low latency and a small binary size on Android, iOS, and other operating
systems.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import multiprocessing
import os
import subprocess
from distutils.command.build_ext import build_ext
import numpy
from setuptools import Extension
from setuptools import find_packages
from setuptools import setup
from setuptools.command.build_py import build_py
PACKAGE_NAME = 'tflite-runtime'
PACKAGE_VERSION = os.environ['TENSORFLOW_VERSION']
DOCLINES = __doc__.split('\n')
PACKAGE = 'tflite_runtime.lite.python'
TENSORFLOW_DIR = os.environ['TENSORFLOW_SRC_ROOT']
# Setup cross compiling
TARGET = (
os.environ['TENSORFLOW_TARGET'] if 'TENSORFLOW_TARGET' in os.environ
else None)
if TARGET == 'rpi':
os.environ['CXX'] = 'arm-linux-gnueabihf-g++'
os.environ['CC'] = 'arm-linux-gnueabihf-g++'
MAKE_CROSS_OPTIONS = ['TARGET=%s' % TARGET] if TARGET else []
RELATIVE_MAKE_DIR = os.path.join('tensorflow', 'lite', 'tools', 'make')
MAKE_DIR = os.path.join(TENSORFLOW_DIR, RELATIVE_MAKE_DIR)
DOWNLOADS_DIR = os.path.join(MAKE_DIR, 'downloads')
RELATIVE_MAKEFILE_PATH = os.path.join(RELATIVE_MAKE_DIR, 'Makefile')
DOWNLOAD_SCRIPT_PATH = os.path.join(MAKE_DIR, 'download_dependencies.sh')
def make_args(target='', quiet=True):
"""Construct make command line."""
args = (['make', 'SHELL=/bin/bash', '-C', TENSORFLOW_DIR]
+ MAKE_CROSS_OPTIONS +
['-f', RELATIVE_MAKEFILE_PATH, '-j',
str(multiprocessing.cpu_count())])
if quiet:
args.append('--quiet')
if target:
args.append(target)
return args
def make_output(target):
"""Invoke make on the target and return output."""
return subprocess.check_output(make_args(target)).decode('utf-8').strip()
def make():
"""Invoke make to build tflite C++ sources.
Build dependencies:
apt-get install swig libjpeg-dev zlib1g-dev python3-dev python3-nump
"""
subprocess.check_call(make_args(quiet=False))
def download_dependencies():
"""Download build dependencies if haven't done yet."""
if not os.path.isdir(DOWNLOADS_DIR) or not os.listdir(DOWNLOADS_DIR):
subprocess.check_call(DOWNLOAD_SCRIPT_PATH)
class CustomBuildExt(build_ext, object):
def run(self):
download_dependencies()
make()
return super(CustomBuildExt, self).run()
class CustomBuildPy(build_py, object):
def run(self):
self.run_command('build_ext')
return super(CustomBuildPy, self).run()
LIB_TFLITE = 'tensorflow-lite'
LIB_TFLITE_DIR = make_output('libdir')
ext = Extension(
name='%s._interpreter_wrapper' % PACKAGE,
language='c++',
sources=['interpreter_wrapper/interpreter_wrapper.i',
'interpreter_wrapper/interpreter_wrapper.cc'],
swig_opts=['-c++',
'-I%s' % TENSORFLOW_DIR,
'-module', 'interpreter_wrapper',
'-outdir', '.'],
extra_compile_args=['-std=c++11'],
include_dirs=[TENSORFLOW_DIR,
os.path.join(TENSORFLOW_DIR, 'tensorflow', 'lite', 'tools',
'pip_package'),
numpy.get_include(),
os.path.join(DOWNLOADS_DIR, 'flatbuffers', 'include'),
os.path.join(DOWNLOADS_DIR, 'absl')],
libraries=[LIB_TFLITE],
library_dirs=[LIB_TFLITE_DIR])
setup(
name=PACKAGE_NAME,
version=PACKAGE_VERSION,
description=DOCLINES[0],
long_description='\n'.join(DOCLINES[2:]),
url='https://www.tensorflow.org/lite/',
author='Google Inc.',
author_email='opensource@google.com',
license='Apache 2.0',
include_package_data=True,
keywords='tflite tensorflow tensor machine learning',
packages=find_packages(exclude=[]),
ext_modules=[ext],
package_dir={PACKAGE: '.'},
cmdclass={
'build_ext': CustomBuildExt,
'build_py': CustomBuildPy,
}
)