2022年7月10日日曜日

YoctoでGoogle CoralのEdgeTPU

 目的


今更ながらGoogle Coralのライブラリgoogle-coral/libedgetpuがbazelでなくてもビルドできることを知った。


なので、これをYoctoのレシピ化して見ることにした。


libedgetpuのレシピ


TensorFlow Liteをレシピ化しているmeta-tensorflow-liteに追加。


レシピ化するときにつまづいた点


すべてではないが、レシピかするときにつまずいた点、ちょっとだけ工夫した点を列挙。


ビルドのワーキングディレクトリの指定

今回、Makefileベースのレシピで作成したが、Makefileはトップディレクトリにない。
このため、${B}でMakefileがあるディレクトリを指定が必要。
ただ、Yoctoのドキュメントには

とあり、タスク[dirs]で指定して、${B}は有効でないとある。

しかしながら、タスク[dirs]で指定してもワークディレクトリは変更されなかった。。。
base.bbclassで上書き${B}で上書きされているので、${B}は必要なんじゃないのかな?
わたしの指定方法がまちがっているかもしれないが。。。


abseil-cppの必要なリンクするライブラリの不足


libedgetpuはabseil-cppのライブラリをいくつかリンクする。
Yoctoのkirkstoneにあるabseil-cppのバージョン( 20211102.0+gitX)はlibedgepuのGrouper(2021.7.27リリース)より新しい。
これが影響してか、ライブラリのリンクに不足(undefined symbol)が発生、パッチで修正した。

また、当初、Yoctoではなく、x86のubuntu22.04上でビルドしてリンク不足の修正を確認していた。その中でabseil-cppをソースビルド&スタティックリンクライブラリ(*.a)をリンクしたところ、undefined symbolが解消できないことがわかった(スタティックリンクだとabseeil-cppの一部がビルドされない?)。
Yoctoのabseil-cppのレシピは共有ライブラリ(*.so)を生成するオプションのため問題はなかったが、この違いによってハマってしまった。

libedgetpuのリポジトリにも同じようなissueがあり、解決できていなかったようなのでコメントしてみた。

gold リンカーを指定するとリンクエラー(risc-v)


RISC-V(meta-riscv)ターゲット向けにビルド時、goldリンカーはないとのエラーが発生する。
libedgetpuのMakefileでは -fuse-ld=gold が指定されている。
ARMターゲット(meta-raspberrypi)ではエラーにならないので、クロスコンパイラの違いが原因と思われる。
なので、Makefileから指定を削除した。



TensorFlow v2.9への対応


もともと、libedgetpuはTensorFlow v2.5のころのソースを一部利用している。
このなかでもcommon.cはC言語のソースだった。

TensorFlow v2.9では、common.cはcommon.ccに変更になっている。

これにあわせて、Makefileを修正している。


xxd: command not foundの解決


edgetpuのfirmwareをビルドする際にxxd(16進数のダンプコマンド)をつかっている。
このxxdコマンド、Yoctoでどのレシピを追加すればよいのかよくわからなかった、、、
OpenEmbedded Layer Indexをつかって検索してもよくわからず、、、

最終的にvim-nativeのレシピ(openembedded-core )を追加することで解決した。
(いつも使うコマンドがどんなパッケージにあるか?ってあまり意識しない時もある。こういうケースでは検索がなかなか大変。。。)


libedgetpu-maxとlibedgetpu-std


libedgetpuには動作周波数を変更する二つのライブラリが存在する。

この2つをレシピ化することにした。
方針としては以下にした。
  • レシピはlibedgetpu-std、libedgetpu-maxとする。
  • 共通部分をcommon.incに切り出して、EXTRA_OEMAKEに指定するフラグとインストールパス(do_install)を定義
  • お互いのレシピは同時に指定されたくないので、RCONFLICTSでコンフリクトするように指定。


ターゲットのBSP


今回は2つのBSPで動作させてみた。

Sipeed Lichee RV Dock向けについては、前回のブログを参照。
meta-riscvからforkしたリポジトリをつかう。

なお、Sipeed Lichee RV Dock向けについては、後述のとおり物体検出やセグメンテーションのモデルはうまく動いていない、、、


イメージの作成


いつもどおり、bitbakeしてみる。
Yoctoのバージョンはkirkstone。


Raspberry Pi 4


まずは、必要なリポジトリをclone。
$ git clone -b kirkstone git://git.yoctoproject.org/poky.git
$ git clone -b kirkstone git://git.yoctoproject.org/meta-raspberrypi
$ git clone -b kirkstone git://git.openembedded.org/meta-openembedded
$ git clone https://github.com/NobuoTsukamoto/meta-tensorflow-lite.git
$ source poky/oe-init-build-env rpi-build

$ bitbake-layers add-layer ../meta-openembedded/meta-oe/
$ bitbake-layers add-layer ../meta-openembedded/meta-python/
$ bitbake-layers add-layer ../meta-openembedded/meta-networking/
$ bitbake-layers add-layer ../meta-openembedded/meta-multimedia/
$ bitbake-layers add-layer ../meta-raspberrypi/
$ bitbake-layers add-layer ../meta-tensorflow-lite/

conf/auto.confに必要なパッケージを追加。
FORTRAN:forcevariable = ",fortran"
MACHINE ?= "raspberrypi4-64"
IMAGE_INSTALL:append = " \
  python3-tensorflow-lite \
  libedgetpu-max \
  opencv \
"
VIDEO_CAMERA = "1"

bitbake。
$ bitbake core-image-weston
...
Build Configuration:
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "universal"
TARGET_SYS           = "aarch64-poky-linux"
MACHINE              = "raspberrypi4-64"
DISTRO               = "poky"
DISTRO_VERSION       = "4.0.1"
TUNE_FEATURES        = "aarch64 armv8a crc cortexa72"
TARGET_FPU           = ""
meta                 
meta-poky            
meta-yocto-bsp       = "kirkstone:4aeda14352a9fa9dd5ba50cf940a2b514fd1ac3c"
meta-oe              
meta-python          
meta-networking      
meta-multimedia      = "kirkstone:fcc7d7eae82be4c180f2e8fa3db90a8ab3be07b7"
meta-raspberrypi     = "kirkstone:0135a02ea577bd39dd552236ead2c5894d89da1d"
meta-tensorflow-lite = "main:4299e649292a9471732e1fff2dc0eb776aba68f5"
...

イメージをSDカードに書き込む。


Sipeed Lichee RV Dock


こちらも同様に必要なリポジトリをclone。
$ git clone -b kirkstone git://git.yoctoproject.org/poky.git
$ git clone -b kirkstone https://github.com/openembedded/openembedded-core.git
$ git clone -b kirkstone https://github.com/openembedded/meta-openembedded.git
$ git clone -b kirkstone_licheerv https://NobuoTsukamoto/riscv/meta-riscv.git
$ git clone https://github.com/NobuoTsukamoto/meta-tensorflow-lite.git
$ source poky/oe-init-build-env licheerv-build

$ bitbake-layers add-layer ../meta-openembedded/meta-oe/
$ bitbake-layers add-layer ../meta-openembedded/meta-python/
$ bitbake-layers add-layer ../meta-openembedded/meta-networking/
$ bitbake-layers add-layer ../meta-openembedded/meta-multimedia/
$ bitbake-layers add-layer ../meta-riscv/
$ bitbake-layers add-layer ../meta-tensorflow-lite/

conf/auto.confに必要なパッケージ・オプションを追加。
FORTRAN:forcevariable = ",fortran"
MACHINE ?= "licheerv"
IMAGE_INSTALL:append = " \
  python3-tensorflow-lite \
  libedgetpu-std \
  opencv \
"

bitbake。
$ bitbake core-image-minimal
...
Build Configuration:
BB_VERSION           = "2.0.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "universal"
TARGET_SYS           = "riscv64-poky-linux"
MACHINE              = "licheerv"
DISTRO               = "poky"
DISTRO_VERSION       = "4.0.1"
TUNE_FEATURES        = "riscv64"
meta                 
meta-poky            
meta-yocto-bsp       = "kirkstone:4aeda14352a9fa9dd5ba50cf940a2b514fd1ac3c"
meta-oe              
meta-python          
meta-networking      
meta-multimedia      = "kirkstone:fcc7d7eae82be4c180f2e8fa3db90a8ab3be07b7"
meta-riscv           = "kirkstone_licheerv:9083c701acede92b2378eb3f0df77fefb8ae29a0"
meta-tensorflow-lite = "main:4299e649292a9471732e1fff2dc0eb776aba68f5"
...

イメージを書き込む。


動作確認


こちらのPythonスクリプトを使っての動作確認。
(レシピ化していないのでSDカードに直接コードとモデルをコピーした)


Raspberry Pi 4


ラズパイ向けでは正常に動作するようだ。


Sipeed Lichee RV Dock


Lichee RV Dockの場合、
  • USBの電力供給の関係で動作しないので、電源供給つきのUSB-HUBが必要。
    device descriptor read/64, error -71 が発生した場合は、電力の不足を疑う。
    (libedgetpu-stdの場合はHUBがなくてもいけるかもしれない)
  • 画像分類モデルはうまく動きそうだが、物体検出やセマンティクス・セグメンテーションのモデルはうまく動作しない。。。
    • 物体検出は結果がすべてNG。
    • セマンティクス・セグメンテーションはポツポツと点のように結果がおかしい。

2つ目の事象は現時点では解決できていない。。。
(なんだかUSBの通信の関係の気がするが、、、)
RISC-V特有でない気もしている。






最後に


ちょっと遅くなったけど、libedgetpuをYoctoのレシピにしてみた。
ラズパイ向けはうまく動いたが、LICHEE RV DOCK向けはおかしい部分がある。

RISC-VのSBCで動けば、おもしろくなってくると思う。
EdgeTPUに限らず、RISC-V+アクセラレーターの構成がEdge AIとしてはありえるんじゃないかな?

2022年7月9日土曜日

YoctoでSipeed Lichee RV Dock

 目的


前回のブログではYoctoのmeta-riscvmeta-tensorflow-liteをつかって、Sipeed Lichee RV DockでOSイメージのビルドとTensorFlow-Liteの動作確認を行った。
ただし、meta-riscvにLichee RV Dock向けの対応(DTSなど)がないためUSBは使えない。

今回は、meta-riscvをforkしてU-Bootやカーネルなどを追加してLichee RV Dock向けBSPを作成して、USBが動作するところまで確認する。


参照


もともと、meta-riscvにはnezha allwinner d1の対応が含まれている。
Yocto Project Summit 2022.05で詳細が発表されていた模様。

これをもとにlinux-sunxiの情報と、 Archlinux Image Builderの情報をもとにBSPを作成してみる。


レシピ(BSP)の作成


meta-riscvをforkして作成。

ブランチは「kirkstone_licheerv」。

コミットはこちら。

おおきくわけて
  • machine configuration
  • boot0
  • opensbi
  • u-boot
  • linux kernel
  • wis
のレシピを変更・追加している。


machine configuration


machine/nezha-allwinner-d1.conf を参考にLichee RV 向けに変更している。

machineは「licheerv」。


boot0


nezha-allwinner-d1向けのレシピに対して修正。
COMPATIBLE_MACHINEに「licheerv」を追加している。


OpenSBI


OpenSBIもnezha-allwinner-d1と同様のであるため、レシピにlicheerv向けの追加を行っているのみ。


U-Boot


こちらはlicheerv向けに作成。

U-Bootのコードはsmaeul/u-bootを利用(ブランチは「d1-wip」)。
他、uEnvやtoc.cfgはnezha-allwinner-d1と同じものを利用。


Linux kernel


こちらもsmaeul/linuxを利用(ブランチは「riscv/d1-wip」)。
defconfigはsehraf/riscv-arch-image-builderのものを利用した(スクリプトから生成)。


wis


nezha-allwinner-d1と同じものを利用。
ただし、いつも参考にしているブログにあるとおりnezha-allwinner-d1のwisではイメージのサイズが大きい(約14GB)。

なので、今回はイメージサイズを約8GB程度にした。

--fixed-size 8000の部分。


イメージ作成(Bitbake)


core-image-minimalでbitbakeしてみる。
まずは、必要なリポジトリをclone。
$ git clone -b kirkstone git://git.yoctoproject.org/poky.git
$ git clone -b kirkstone https://github.com/openembedded/openembedded-core.git
$ git clone -b kirkstone https://github.com/openembedded/meta-openembedded.git
$ git clone -b kirkstone_licheerv https://NobuoTsukamoto/riscv/meta-riscv.git
$ source poky/oe-init-build-env licheerv-build

$ bitbake-layers add-layer ../meta-openembedded/meta-oe/
$ bitbake-layers add-layer ../meta-openembedded/meta-python/
$ bitbake-layers add-layer ../meta-openembedded/meta-networking/
$ bitbake-layers add-layer ../meta-openembedded/meta-multimedia/
$ bitbake-layers add-layer ../meta-riscv/

あとは、bitbake。
MACHINE=licheerv bitbake core-image-minimal

成功したら、*.wic.gzファイルをSDカードに書き込んでブートさせてみる。


動作確認




core-image-westonもやってみる


bitbakeでcore-image-westonをビルドして動かしてみた。



最後に


今回はRISC-V SBCのSipeed Lichee RV Dock向けのBSPをmeta-riscvのnezha-allwinner-d1を参考にやってみた。