Desplegando una TPU en Raspberry
Introducción
El acelerador USB Coral de Google es un dipositivo que proporciona un coprocesador neural a tu CPU. Lo has adivinado, seguramente te sonará a la música de orquesta (con coros de fondo) que ha sonado durante los últimos meses con respecto al ARM64 M1 de Apple. El M1 también posee en formato SoC un coprocesador neural con 16 núcleos.
Pero volvamos al dipositivo en cuestión. Éste acelera modelos de Machine Learning en un contexto, eso sí, de inferencia o predicción. Eso siempre y cuando lo acoples a un dispositivo de host y no se te quede olvidado dentro del bolsillo.
En este post nos hemos propuesto revitalizar nuestra vieja e infrautilizada Raspberry Pi 3 pero, en general, puedes repetir el ejercicio con cualquier ordenador al uso y en cualquier entorno operativo moderno, aunque, como casi siempre con linux y específicamente basadas en debian, siempre te será más fácil llegar al resultado final.
Las conclusiones son bastantes prometedoras y apuntan a que obtendremos mejores resultados (tiempos de ejecución) pasadas las Navidades cuando estemos provistos de la siguiente iteración de Raspberry Pi (la 4). Lo exponemos a continuación.
1: Instalar el entorno de ejecución edgetpu
Añadimos los repositorios tipo deb de Google Cloud (esto es transparente e independiente de plataforma: ni siquiera te tienes que preocupar de si estás en un pc convencional o un dipositivo IoT como la raspi3):
$ echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list $ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - $ sudo apt update
Instalación vía apt:
$ sudo apt install libedgetpu1-std
Conexión en caliente del Coral. En el caso de la raspi3: no te queda más remedio de tirar de un puerto USB 2.0. Y esto será limitante (como veremos).
Eres valiente, hace frío y sólo se vive una vez. Aceptas hacer overclocking al edgetpu:
$ sudo apt install libedgetpu1-max
DISCLAIMER: Este último paso pone en modo overclocking automáticamente el edgetpu hasta que, volviendo a instalar el modo estandar libedgetpu1-std, conmutes a modo normal.
2: Instalar la librería TensorFlow Lite
Por higiene y robustez ante posibles incendios, empezamos por generar un entorno aislado para correr modelos en formato tflite. Somos bastante fans de instalaciones mínimas de python bien sea por trabajo, porque no nos "cabe" anaconda o miniconda en una raspi3 o, simplemente, porque nos sobra con pip y con venv. En lo que sigue abandonamos privilegios de su (python good practice) y al lío:
$ cd ~ $ python3 -m venv tflite_runtime $ source tflite_runtime/bin/activate (tflite_runtime)$ pip3 install https://github.com/google-coral/pycoral/releases/download/release-frogfish/tflite_runtime-2.5.0-cp37-cp37m-linux_armv7l.whl
Se escoge este wheel por que a día de hoy la versión de python que corre en máquinas ARMv7 como la raspi3, es la 3.7. Listando, obtenemos las librerías visibles desde el entorno tflite_runtime:
(tflite_runtime)$ pip3 list Package Version -------------- ------- numpy 1.19.4 pip 18.1 pkg-resources 0.0.0 setuptools 40.8.0 tflite-runtime 2.5.0
3: Jugando a Predecir
Vale. Muy bien. ¿Ya lo tenemos todo?
Lo primero que habría que ver es si nuestro host ha detectado la conexión vía USB del edgetpu. Veamos:
(tflite_runtime)$ lsusb | grep Google Bus 001 Device 006: ID 18d1:9302 Google Inc.
Está conectado y Google sigue tan oscurantista como siempre (han visto demasiadas veces #devs en Mountain View):
(tflite_runtime)$ lsusb -v | grep Google can't get debug descriptor: Resource temporarily unavailable Bus 001 Device 006: ID 18d1:9302 Google Inc. idVendor 0x18d1 Google Inc. Couldn't open device, some information will be missing Couldn't open device, some information will be missing Couldn't open device, some information will be missing Couldn't open device, some information will be missing
Dan mucha pereza.
A continuación, deberíamos hacer los consiguientes testeos con scripts de python y modelos Tensorflow correctamente cuantizados (volveremos a esto en próximos posts) y adaptados para correr en el edgetpu. Afortunadamente, tenemos scripts de prueba en el github del proyecto. Para esto no necesariamente nos hemos de mantener en el entorno virtual tflite_runtime, pero por claridad en la exposición y dado que para correr estos tests será necesario volver a activarlo, nos mantenemos en éste.
(tflite_runtime)$ sudo apt install git (tflite_runtime)$ mkdir ~/coral && cd coral (tflite_runtime)$ git clone https://github.com/google-coral/tflite.git
Lo siguiente va a ser instalar Pillow vía pip asistidos por un script de shell install_requirements.sh, que Google nos proporciona en el github del proyecto. Este script de shell, además, nos baja datos reales así como archivos de modelos compilados en formato tflite:
(tflite_runtime)$ cd tflite/python/examples/classification/ (tflite_runtime)$ ./install_requirements.sh
Et voilà. Ya podemos darle caña:
(tflite_runtime)$ python3 classify_image.py --model models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite --labels models/inat_bird_labels.txt --input images/parrot.jpg ----INFERENCE TIME---- Note: The first inference on Edge TPU is slow because it includes loading the model into Edge TPU memory. 122.7ms 10.5ms 10.5ms 10.6ms 10.5ms -------RESULTS-------- Ara macao (Scarlet Macaw): 0.77734
¿Lento? Vamos a pasarle la carga de trabajo a la pobre CPU de la raspi3. Sin overclocking, un procesador ARMv8 que a duras apenas corre a 1.2GHz.
Básicamente, consiste en pasarle la misma carga de inferencia y modelo cuantizado a la Raspberry pero sin las optimizaciones para el edgetpu. Esto se consigue sustituyendo el archivo de compilado tflite que contiene estas optimizaciones.
Ambos versiones de compilados para Tensorflow Lite están bajo el directorio models/:
(tflite_runtime) $ ls -l models/*tflite -rw-r--r-- 1 pi pi 3531296 Dec 7 11:49 models/mobilenet_v2_1.0_224_inat_bird_quant.tflite -rw-r--r-- 1 pi pi 4067912 Dec 7 11:49 models/mobilenet_v2_1.0_224_inat_bird_quant_edgetpu.tflite
Y con la sustitución y posterior ejecución.
(tflite_runtime)$ python3 classify_image.py --model models/mobilenet_v2_1.0_224_inat_bird_quant.tflite --labels models/inat_bird_labels.txt --input images/parrot.jpg ----INFERENCE TIME---- Note: The first inference on Edge TPU is slow because it includes loading the model into Edge TPU memory. 334.1ms 267.0ms 266.9ms 266.8ms 266.8ms -------RESULTS-------- Ara macao (Scarlet Macaw): 0.77734
Sensiblemente más lento que activando la TPU que además está penalizada por la conexión (lenta) USB 2.0.
Conclusiones
Hemos aprendido a desplegar una TPU como el Coral de Google en un dispositivo de mínimo consumo, superportable y fácilmente monitorizable en remoto como es la Raspberry Pi en su iteración 3. El dispositivo acelera los problemas de predicción que como contraste se proporcionan desde el proyecto google-coral, si se compara con el rendimiento de la CPU del host.
Cabría investigar como de grande es la penalización por utilizar una conexión lenta USB 2.0 (la raspi3 no tiene puertos USB 3.0) y cuánta mejora se obtiene contra una CPU más común en un entorno de desarrollo (linux) similar.
Pero eso es, otra historia. Y os la contaremos en el próximo post ;-)












