| 231 | == Upstream / Mainline NPU support |
| 232 | The IMX8MP has a Verisilicon NPU which is from Vivante. Vivante supports this via their vivante driver (/dev/galcore) but that is not an opensource driver so it would make sense to want to support the NPU with it's opensource equivalent (etnaviv driver). Support for this has been added to the Linux 6.10 kernel. |
| 233 | |
| 234 | The userspace library used for GPU is mesa so it makes sense to support the NPU there as well and for hardware accelleration this is done in mesa with 'delegate' libraries. While Support for the !VeriSilicon NPU made it into Mesa 24.1.0 via teflon it does not yest support the imx8mp which has a sightly newer version of the !VeriSilicon NPU. |
| 235 | |
| 236 | Therefore to support the NPU you need to build a custom fork of mesa that is being worked on by [https://blog.tomeuvizoso.net/ Tomeu Vizoso] with the work being sponsored by [https://ideasonboard.com/ Ideas On board]. |
| 237 | |
| 238 | On a Gateworks Venice board with an IMX8MP and Ubuntu 22.04 (jammy) root filesystem: |
| 239 | - update kernel to v6.10 with NPU support |
| 240 | {{{#!bash |
| 241 | # update kernel |
| 242 | cd /tmp && wget https://dev.gateworks.com/venice/kernel/linux-venice-6.10.6.tar.xz && tar -C / -xvf linux*.tar.xz --keep-directory-symlink && reboot |
| 243 | }}} |
| 244 | - create a non-root user (always a good idea but not required for mesa) |
| 245 | {{{#!bash |
| 246 | # create user |
| 247 | USER=gateworks |
| 248 | useradd -s /bin/bash $USER |
| 249 | mkdir /home/$USER; chown $USER /home/$USER |
| 250 | # allow sudo for this user |
| 251 | echo "$USER ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers |
| 252 | # add render group (needed for some examples) |
| 253 | usermod -aG render $USER |
| 254 | # login as this user |
| 255 | su -l $USER |
| 256 | }}} |
| 257 | - install python virtualenv which allows us to prevent conflicts between package libraries |
| 258 | {{{#!bash |
| 259 | sudo apt update && sudo apt upgrade -y && sudo apt install -y python3-pip python3-venv |
| 260 | # create tflite1-env" virtualenv |
| 261 | python3 -m venv tflite1-env |
| 262 | # activate the venv (repeat or every new shell) |
| 263 | source tflite1-env/bin/activate |
| 264 | }}} |
| 265 | - build mesa (fork with updated teflon support for imx8mp) |
| 266 | {{{#!bash |
| 267 | # install build deps |
| 268 | sudo apt install -y build-essential git cmake |
| 269 | sudo apt-get -y build-dep mesa |
| 270 | # get repo |
| 271 | git clone https://gitlab.freedesktop.org/tomeu/mesa.git -b etnaviv-imx8mp mesa |
| 272 | cd mesa |
| 273 | # mesa requires meson >= 1.1.0 (newer than jammy's), pycparser >= 2.20, and mako |
| 274 | pip3 install meson pycparser mako |
| 275 | ~/tflite1-env/bin/meson setup build -Dgallium-drivers=etnaviv -Dvulkan-drivers= -Dteflon=true |
| 276 | ~/tflite1-env/bin/meson compile -C build # 20 mins or so on imx8mp |
| 277 | ldd build/src/gallium/targets/teflon/libteflon.so |
| 278 | }}} |
| 279 | - install tensorflow lite runtime |
| 280 | {{{#!bash |
| 281 | # install tensorflow lite runtime |
| 282 | pip3 install tflite_runtime |
| 283 | # clone tensorflow for some examples and assets used below |
| 284 | cd |
| 285 | git clone https://github.com/tensorflow/tensorflow.git |
| 286 | }}} |
| 287 | - run teflon image classification test |
| 288 | {{{#!bash |
| 289 | # note this test requires python pillow, python numpy<2.0 and write access to /dev/dri/renderD128 |
| 290 | pip3 install "numpy<2.0" pillow tflite_runtime # tflite_runtime requires pillow as well as numpy<2 |
| 291 | groups # make sure your in the render group (or have write access to /dev/dri/renderD128) |
| 292 | # without teflon (175.335ms on imx8mp) |
| 293 | python3 ~/mesa/src/gallium/frontends/teflon/tests/classification.py \ |
| 294 | -i ~/tensorflow/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp \ |
| 295 | -m ~/mesa/src/gallium/targets/teflon/tests/mobilenet_v1_1.0_224_quant.tflite \ |
| 296 | -l ~/mesa/src/gallium/frontends/teflon/tests/labels_mobilenet_quant_v1_224.txt \ |
| 297 | # with teflon (7.651ms on imx8mp) |
| 298 | python3 ~/mesa/src/gallium/frontends/teflon/tests/classification.py \ |
| 299 | -i ~/tensorflow/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp \ |
| 300 | -m ~/mesa/src/gallium/targets/teflon/tests/mobilenet_v1_1.0_224_quant.tflite \ |
| 301 | -l ~/mesa/src/gallium/frontends/teflon/tests/labels_mobilenet_quant_v1_224.txt \ |
| 302 | -e ~/mesa/build/src/gallium/targets/teflon/libteflon.so |
| 303 | }}} |
| 304 | - run tensorflow label_image example: |
| 305 | {{{#!bash |
| 306 | # we need to patch the label_image example to use tflite_runtime |
| 307 | cd ~/tensorflow |
| 308 | cat <<EOF | |
| 309 | diff --git a/tensorflow/lite/examples/python/label_image.py b/tensorflow/lite/examples/python/label_image.py |
| 310 | index d26454f921f..08c65962bf1 100644 |
| 311 | --- a/tensorflow/lite/examples/python/label_image.py |
| 312 | +++ b/tensorflow/lite/examples/python/label_image.py |
| 313 | @@ -19,7 +19,7 @@ import time |
230 | | |
231 | | |
232 | | |
233 | | |
| 315 | import numpy as np |
| 316 | from PIL import Image |
| 317 | -import tensorflow as tf |
| 318 | +import tflite_runtime.interpreter as tflite |
| 319 | |
| 320 | |
| 321 | def load_labels(filename): |
| 322 | @@ -85,7 +85,7 @@ if __name__ == '__main__': |
| 323 | tflite.load_delegate(args.ext_delegate, ext_delegate_options) |
| 324 | ] |
| 325 | |
| 326 | - interpreter = tf.lite.Interpreter( |
| 327 | + interpreter = tflite.Interpreter( |
| 328 | model_path=args.model_file, |
| 329 | experimental_delegates=ext_delegate, |
| 330 | num_threads=args.num_threads) |
| 331 | |
| 332 | EOF |
| 333 | patch -p1 |
| 334 | # without acceleration (175.993ms on imx8mp) |
| 335 | python3 ~/tensorflow/lite/examples/python/label_image.py \ |
| 336 | -m ~/mesa/src/gallium/targets/teflon/tests/mobilenet_v1_1.0_224_quant.tflite \ |
| 337 | -l ~/mesa/src/gallium/frontends/teflon/tests/labels_mobilenet_quant_v1_224.txt \ |
| 338 | -i ~/tensorflow/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp |
| 339 | # with acceleration (14.138ms on imx8mp) |
| 340 | python3 ~/tensorflow/lite/examples/python/label_image.py \ |
| 341 | -m ~/mesa/src/gallium/targets/teflon/tests/mobilenet_v1_1.0_224_quant.tflite \ |
| 342 | -l ~/mesa/src/gallium/frontends/teflon/tests/labels_mobilenet_quant_v1_224.txt \ |
| 343 | -i ~/tensorflow/tensorflow/lite/examples/label_image/testdata/grace_hopper.bmp \ |
| 344 | -e ~/mesa/build/src/gallium/targets/teflon/libteflon.so |
| 345 | }}} |
| 346 | |
| 347 | |
| 348 | |
| 349 | |