google-coral / libedgetpu

Source code for the userspace level runtime driver for Coral.ai devices.
Apache License 2.0
181 stars 62 forks source link

Illegal Instruction for armv7-a #3

Closed cristianwpuig closed 3 years ago

cristianwpuig commented 3 years ago

Hi, there!

First of all, I wanted to thank you for this awesome repository! I'm trying to install edgetpu runtime on an ARMv7 SAMA5d3 cpu with Debian buster and python 3.7 and at the same time using Debian stretch and python 3.5. With both I have the same illegal instruction error. I'm going to explain the steps I followed for both.

$ uname -s
Linux
$ uname -r
4.4.36-sama5-armv7-r8
$ uname -m
armv7l

libedgetpu1-std version 14.1
tflite-runtime version  2.1.0.post1
$ python3 -c 'print(__import__("tflite_runtime").__git_version__)'
0.6.0-76902-gd855adfc5a
Debian 10 gcc version 8.3.0
Debian 9 gcc version 6.3.0

I started following the steps of getting started web:

$ sudo apt-get install libedgetpu1-std
$ pip3 install https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp35-cp35m-linux_armv7l.whl (37 for py3.7)
$ git clone https://github.com/google-coral/tflite.git
$ cd tflite/python/examples/classification
$ bash install_requirements.sh
$ 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
Illegal instruction

Then, I got an illegal instruction error, and I verified that the error comes from /usr/lib/arm-linux-gnueabihf/libedgetpu.so.1.0 file. Then, I tried to cross compile libedgetpu.so.1.0 using this library (google-coral/libedgetpu) in an Ubuntu 18.04 x86_64 as a host using the following: $ sudo DOCKER_CPUS="armv7a" DOCKER_TARGETS=libedgetpu-throttled make docker-build

The target cpu that I'm using not accept all the optimizations

$ lscpu:
Architecture:        armv7l
Byte Order:          Little Endian
CPU(s):              1
On-line CPU(s) list: 0
Thread(s) per core:  1
Core(s) per socket:  1
Socket(s):           1
Model:               1
Model name:          Cortex-A5
Stepping:            r0p1
BogoMIPS:            351.43
Flags:               half thumb fastmult vfp edsp vfpv3 vfpv3d16 tls vfpv4

$ cat /proc/cpuinfo:
model name      : ARMv7 Processor rev 1 (v7l)
CPU implementer : 0x41
CPU architecture: 7
Hardware        : Atmel SAMA5

For this reason, I'm trying to comment on some lines in the cc_toolchain_config.bzl.tpl file such as line 130 due to neon optimizations are not admitted. Then, I copy the libedgetpu.so.1.0 generated into /usr/lib/arm-linux-gnueabihf of my armv7 and I still getting illegal instruction error. I'm reading the gcc manual to check if my cpu admits the flags used. Many attempts later, commenting several lines and adding some ( final cc_toolchain_config.bzl.tpl file ), I achieved that before printing illegal instruction when running classify_image.py it prints:

[  777.610000] usb 1-3: reset high-speed USB device number 3 using atmel-ehci
[  779.010000] usb 1-3: USB disconnect, device number 3
[  779.820000] usb 1-3: new high-speed USB device number 4 using atmel-ehci
[  779.970000] usb 1-3: New USB device found, idVendor=18d1, idProduct=9302
[  779.970000] usb 1-3: New USB device strings: Mfr=0, Product=0, SerialNumber=0
Illegal instruction

But when I do import edgetpu:

$ python3
Python 3.5.3 (default, Jul  9 2020, 13:00:10)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import edgetpu
Illegal instruction

I'm still getting Illegal Instruction

Would really appreciate any help or advice. Thank you.

Namburger commented 3 years ago

@cristianwpuig ahh, okay, this is probably one of a harder issue to diagnose, since this could be libedgetpu.so or tflite_runtime package... or both. Let's make the assumption that libedgetpu is the caused, make sure you remove our build and use yours. Maybe these command can give some insight:

file libedgetpu.so.1.0
ldd libedgetpu.so.1.0
python3 -c "from ctypes import *; cdll.LoadLibrary('libedgetpu.so.1.0'); print('success')" 
cristianwpuig commented 3 years ago

Hi @Namburger, Thanks for your helpful and quick reply!

First of all, I made the commands with the original libedgetpu.so.1.0 (installed with google-coral/edgetpu library)

$ file /usr/lib/arm-linux-gnueabihf/libedgetpu.so.1.0
libedgetpu.so.1.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=8ec7cf99db9ebfeee36a1f0c1e64f73fd7dbbdd0, stripped

$ python3 -c "from ctypes import *; cdll.LoadLibrary('libedgetpu.so.1.0'); print('success')" 
Illegal instruction

Then, I have performed these commands using my custom build on the armv7 platform.

$ file /usr/lib/arm-linux-gnueabihf/libedgetpu.so.1.0
libedgetpu.so.1.0: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=e3a56a535799e5bb2d8d3f0151c2cb9de31c33bb, stripped
$ ldd /usr/lib/arm-linux-gnueabihf/libedgetpu.so.1.0
        libusb-1.0.so.0 => /lib/arm-linux-gnueabihf/libusb-1.0.so.0 (0xb6de2000)
        libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 (0xb6cd6000)
        libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xb6c5e000)
        libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb6c35000)
        libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6c11000)
        libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6b23000)
        /lib/ld-linux-armhf.so.3 (0x7f5e9000)
        libudev.so.1 => /lib/arm-linux-gnueabihf/libudev.so.1 (0xb6b0c000)
        librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6af6000)
$ python3 -c "from ctypes import *; cdll.LoadLibrary('libedgetpu.so.1.0'); print('success')" 
success

and yipee:tada:!! :) Now, I can confirm that the libedgetpu.so.1.0 file works. Thank you for these wonderful commands. Now I will check the tflite_runtime package.

Thank you very much @Namburger, I've been stuck for a few days, and it was just what I needed. When I get it, I will make a pull request with my custom files, and you can include another platform in this wonderful project :)

Namburger commented 3 years ago

@cristianwpuig No problems, should have reached out reach out earlier :) You can use these instructions to build tflite_runtime package. Make sure that you first check out the same tensorflow commit as our tensorflow dependency or you'll run into another issue.

FYI: Similar things has been done for supports with the RPI0, since we don't support armv6 any longer (slightly related to issue that you're having). Anyhow, our PRs process is a little "off" currently due to some internal process that we have to go through. However I'll definitely bring this up on our meeting and will keep you updated.

cristianwpuig commented 3 years ago

Thank you one more time @Namburger :v: I will report my progress!

cristianwpuig commented 3 years ago

Finally I got it! :tada: :tada:

I started generating libedgetpu.so as said before, then i installed libegdetpu in the Armv7 with the following steps:

git clone https://github.com/google-coral/edgetpu
git checkout 61ea4998c938c6ee7c964582df529aea4327d055
cd edgetpu-61ea4998c938c6ee7c964582df529aea4327d055
bash scripts/runtime/install.sh

And then copy the libedgetpu.so previously cross compiles to/usr/lib/arm-linux-gnueabihf/ in the Armv7

Now we have to install tflite from source in the Armv7 following this steps:

* Install python3.6
git clone https://github.com/tensorflow/tensorflow && cd tensorflow
git checkout f394a768719a55b5c351ed1ecab2ec6f16f99dd4
cd tensorflow-f394a768719a55b5c351ed1ecab2ec6f16f99dd4
sudo apt install swig libjpeg-dev zlib1g-dev python3-dev python3-numpy
sudo apt-get install pybind11-dev
pip3 install pybind11, numpy
sudo apt-get install libeigen3-dev
sudo bash tensorflow/lite/tools/make/download_dependencies.sh
sudo bash tensorflow/lite/tools/pip_package/build_pip_package.sh
pip3 install /tensorflow/lite/tools/pip_package/gen/tflite_pip/python3.6/dist/tflite_runtime-2.1.0-cp36-cp36m-linux_armv7l.whl

And yuhu!! You have now installed tflite along with libedgetpu in an Armv7 CPU without using some instructions such as Neon. Now you can go to https://coral.ai/docs/accelerator/get-started/ and running the model making the step 3 without any error!

NOTE: If during the compilation of the tflite package you get an error such as:

In file included from interpreter_wrapper/interpreter_wrapper_pybind11.cc:20:
/tensorflow/tensorflow/lite/tools/pip_package/../../../../tensorflow/python/lib/core/pybind11_lib.h:16:10: fatal error: include/pybind11/pybind11.h: No such file or directory
 #include "include/pybind11/pybind11.h"

You can solve it following the next steps:

1. In /tensorflow-f394a768719a55b5c351ed1ecab2ec6f16f99dd4/tensorflow/lite/tools/pip_package/Dockerfile Add pybind11-dev \ belowpython-pip \ line

2. In /tensorflow-f394a768719a55b5c351ed1ecab2ec6f16f99dd4/tensorflow/lite/tools/pip_package/setup.py add: import pybind11 And change this line:

        os.path.join(DOWNLOADS_DIR, 'absl')
    ] + get_pybind_include(),

With this:

        os.path.join(DOWNLOADS_DIR, 'absl'),
        pybind11.get_include()
    ],

3. Cahnge the include lines of the package pybind11 in /tensorflow-f394a768719a55b5c351ed1ecab2ec6f16f99dd4/tensorflow/lite/python/interpreter_wrapper/interpreter_wrapper_pybind11.cc so they look like this:

#include "pybind11/functional.h"
#include "pybind11/pybind11.h"
#include "pybind11/pytypes.h"
#include "pybind11/stl.h"
  1. Cahnge the include lines of the package pybind11 in /tensorflow-f394a768719a55b5c351ed1ecab2ec6f16f99dd4/tensorflow/python/lib/core/pybind11_lib.h so they look like this:

#include "pybind11/pybind11.h"
#include "pybind11/pytypes.h"

Thank you for everything @Namburger!!:v: