#はじめに
この記事はOpenCV Advent Calendar 2018の5日目の記事です.
他の記事は目次にまとめられています.
なお、本記事は筆者個人の意見であり、筆者の所属組織とは無関係です。
この話のオチ
OpenCV on RISC-V いけます!! (2018/12/2 確認)
RISC-Vとは?
オープンな命令セットを共有することで、ソフトウェアの互換性が高まる!!という夢に基づいたもの。
- PCから組み込みまで、幅広く使わえる(かもしれない)
- 現状の「Intel/AMD」「ARM」に対する、第三の選択肢になる(かもしれない)。
- 独自に命令拡張したりすることも可能である。
SHとか78とかマイコン世界が楽しいとか言ってはいけない
RISC-V エミュレータ環境構築
ではまず、エミュレータを動かすところから。
こちらをベースに作業をしました。
http://msyksphinz.hatenablog.com/entry/2018/09/24/040000
2018/12/1 現在、Ubutntu 18.04 をベースに作業をしました。
①ISSUE1: e2fsprogのコンパイル時に「名前衝突」で怒られ、失敗。
./output/build/host-e2fsprogs1.43.1/misc/create_inode.c
copy_file_range() が名前重複で引っかかる。
staticな関数だったため、_copy_file_range() に変更して問題回避。
②ISSUE2: automakeの変換部分で引っかかる。
Perlのバージョンでそのままだと、うまくいかないことがあるらしい。
下記内容を見て、修正。
buildroot-riscv-2018-09-22/output/host/usr/bin/automake
L3936
https://github.com/raspberrypi/noobs/issues/470
③ISSUE3: ワークディスクがない
このまま環境を用意すると、ディスクが少なすぎて何かするのも大変なので、qemuでディスクを作り、cfgに追加。
[HOST] $ qemu-img create -f raw raw.img 4G
[HOST] $ mkfs.ext3 raw.img
/* VM configuration file */
{
version: 1,
machine: "riscv64",
memory_size: 512,
bios: "bbl64.bin",
cmdline: "console=hvc0 root=/dev/vda rw",
drive0: { file: "../buildroot-riscv-2018-09-22/output/images/rootfs.ext2" },
drive1: { file: "./raw.img" },
eth0: { driver: "user" },
}
増設した方のディスクは、/dev/vdb として認識される。
なお、めんどくさがってパーティションも切らない悪い子です。
RISC-V エミュレータ(temu)を動かしてみよう
../temu-2018-09-15/temu root-riscv64.cfg -m 512 -rw
temuを止めるには、C-a x (QEmuと同じ) <- 重要
クロスコンパイルを動かそう(ゴゴゴゴゴ
クロスコンパイル用の設定ファイル
はーい、ここではあらかじめ用意したこちらを以下略。
https://raw.githubusercontent.com/Kumataro/opencv/master/platforms/linux/riscv.toolchain.cmake
https://raw.githubusercontent.com/Kumataro/opencv/master/platforms/linux/riscv64-gnu.toolchain.cmake
FLOAT_ABIほにゃららの残骸が残ってた… キニシナイ
パスを通す
[HOST] export PATH="${PATH}:~/workRiscV/buildroot-riscv-2018-09-22/output/host/usr/bin/"
コンパイルする
[HOST] mkdir build && cd build
[HOST] cmake -DCMAKE_TOOLCHAIN_FILE=../platforms/linux/riscv.tootlchain.cmake ..
[HOST] cmake-gui ../ ← ここで不要そうなパッケージ外しまくる
[HOST] make -j8
[HOST] make install ← これをやると成果物が、build/install にまとまる。
動かしてみる
OpenCVのコンパイル成果物他を、tmpにコピーして持ち出す。
(libstdとかなんでやる必要があるのかわからないけど、とりあえずエラーになるので対策してみた。)
[HOST] $ sudo -s
[HOST] % mkdir tmp
[HOST] % mount raw.img tmp
[HOST] % rsync -avz ../../../opencv-4.0.0/build/install tmp/opencv
[HOST] % umouont tmp
[TARGET] $ mount /dev/vdb /mnt
[TARGET] $ LD_PRELOAD=../lib/libopencv_core.so.4.0:/usr/lib/libstdc++.so.6:/usr/lib/libgcc_s.so.1 ./opencv_version
実行画面がこちら。cpuinfoがよくわからない!!(正しい)
そして、生成物のライブラリをobjdump してみた…… うん!!!わからん!!(正しい)
0000000000066b76 <_ZN2cv3hal12cvtGraytoBGREPKhmPhmiiii>:
66b76: 7169 addi sp,sp,-304
66b78: e64e sd s3,264(sp)
66b7a: 01810993 addi s3,sp,24
66b7e: f9da sd s6,240(sp)
66b80: f5de sd s7,232(sp)
66b82: 8b2e mv s6,a1
66b84: 8baa mv s7,a0
66b86: 00174597 auipc a1,0x174
66b8a: 0d258593 addi a1,a1,210 # 1dac58 <_ZZN2cv3hal12cvtGraytoBGREPKhmPhmiiiiE26__cv_trace_location_fn1447>
#画像も扱おう
実行ファイルを作る
クロスコンパイル環境でのやり方になれていないので、力技使いまくりです。
#include <stdio.h>
#include <opencv2/opencv.hpp>
int main()
{
cv::Mat mat;
mat = cv::imread("lena.jpg");
cv::putText(mat, "OpenCV meets RISC-V", cv::Point(50,50),
cv::FONT_HERSHEY_SIMPLEX,
1.2, cv::Scalar(255,255,255), 2 );
cv::imwrite("lena_hello.jpg", mat);
return 0;
}
ここまではまだよい。
~/workRiscV/buildroot-riscv-2018-09-22/output/host/usr/bin/riscv64-linux-g++ a.cpp -o a.out \
-I../opencv-4.0.0/build4/install/include/opencv4 \
-L../opencv-4.0.0/build4/install/lib \
-lrt -lm -lpthread -ldl \
-lopencv_core \
-lopencv_imgcodecs \
-lopencv_imgproc
これで作ったa.out を、raw.img経由で、temu環境に持ち出す。
動かしてみる
が、ld関係がなんかうまく作れなかったので「力づく」でねじ伏せる(良い子は絶対にまねしてはならない)
[TARGET] LD_PRELOAD=./opencv/lib/libopencv_calib3d.so:./opencv/lib/libopencv_core.so:./opencv/lib/libopencv_dnn.so:./opencv/lib/libopencv_features2d.so:./opencv/lib/libopencv_flann.so:./opencv/lib/libopencv_gapi.so:./opencv/lib/libopencv_highgui.so:./opencv/lib/libopencv_imgcodecs.so:./opencv/lib/libopencv_imgproc.so:./opencv/lib/libopencv_ml.so:./opencv/lib/libopencv_objdetect.so:./opencv/lib/libopencv_photo.so:./opencv/lib/libopencv_stitching.so:./opencv/lib/libopencv_video.so:./opencv/lib/libopencv_videoio.so::/usr/lib/libstdc++.so.6:/usr/lib/libgcc_s.so.1 ./app/a.out
実行結果
RISC-V上でOpenCVモジュールを使い、
- ①JPG画像をMatに展開し、
- ②文字描画コマンドを介して画素にアクセスし、
- ③MatをJPEG画像に保存できる、
ことができました!!お疲れ様でございました!!
速度は…
まあ、Soft Emulationだし遅いのは今の時点では仕方がない…。(core i7 4770上のtemu上で測定)
[root@localhost mnt]# time sh exe.sh
real 0m 3.03s
user 0m 2.79s
sys 0m 0.22s
まとめ
OpenCVは、RISC-V上でも動かせる!
OpenCV on RISC-V いけます!! (2018/12/2 確認)
ただし、性能検証や精度検証するには、ハードが欲しい。
今後の展望(OpenCV on RISC-V)
risc-vの多様な構成をどう扱うのか。
もう一度、このcpuinfoをご覧ください。
https://www.aps-web.jp/academy/risc-v/02/
https://en.wikipedia.org/wiki/RISC-V によると
rv64acdfimsu というのは、
文字列 | 意味 |
---|---|
64i | Base Integer Instruction Set, 64-bit |
a | Atomic拡張 |
c | 16bit短縮命令 |
d | 倍精度浮動小数点 |
f | 単精度浮動小数点 |
m | 乗除算命令 |
s | スーパーバイザモード |
u | ? |
さて、となると「倍精度浮動小数」やら「単精度浮動小数」の扱いや、更には「4倍精度浮動小数点」の扱いなんかも考えないといけないということですね。
組込目的だけであれば、もちろん固定のプロファイルでよいのですが…というのが少し悩ましい感じです。
risc-v対応SIMD検討
RISC-VにもSIMDの仕組みはある、のだからやらないと性能が十分に発揮できない、ということになってしまいますね。
そして、128bit CPUへ・・・
そして128bitにも対応しています。
これは、まず、まともに動くのか、というレベルの検討からですね・・・
はーい、明日の予告は
明日は @fukushima1981 さんの記事で,タイトルは「リアルタイム画像処理のための動体視力を求めない」となっています.もう私もおじいちゃんなので、うれしい記事ですね、きっと!!!
設定ファイル
今回の試作は以下の設定になりました。
General configuration for OpenCV 4.0.0 =====================================
Version control: unknown
Platform:
Timestamp: 2018-12-02T02:09:41Z
Host: Linux 4.15.0-39-generic x86_64
Target: Linux 1 riscv64
CMake: 3.10.2
CMake generator: Unix Makefiles
CMake build tool: /usr/bin/make
Configuration: Release
CPU/HW features:
Baseline:
requested: DETECT
C/C++:
Built as dynamic libs?: YES
C++ Compiler: /home/kumataro/workRiscV/buildroot-riscv-2018-09-22/output/host/usr/bin/riscv64-linux-g++ (ver 7.3.0)
C++ flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-unnamed-type-template-args -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -DNDEBUG
C++ flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-unnamed-type-template-args -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden -g -O0 -DDEBUG -D_DEBUG
C Compiler: /home/kumataro/workRiscV/buildroot-riscv-2018-09-22/output/host/usr/bin/riscv64-linux-gcc
C flags (Release): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-unnamed-type-template-args -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden -O3 -DNDEBUG -DNDEBUG
C flags (Debug): -fsigned-char -W -Wall -Werror=return-type -Werror=non-virtual-dtor -Werror=address -Werror=sequence-point -Wformat -Werror=format-security -Wmissing-declarations -Wmissing-prototypes -Wstrict-prototypes -Wundef -Winit-self -Wpointer-arith -Wshadow -Wsign-promo -Wuninitialized -Winit-self -Wsuggest-override -Wno-narrowing -Wno-delete-non-virtual-dtor -Wno-unnamed-type-template-args -Wno-comment -Wimplicit-fallthrough=3 -Wno-strict-overflow -fdiagnostics-show-option -pthread -fomit-frame-pointer -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden -g -O0 -DDEBUG -D_DEBUG
Linker flags (Release):
Linker flags (Debug):
ccache: NO
Precompiled headers: NO
Extra dependencies: dl m pthread rt
3rdparty dependencies:
OpenCV modules:
To be built: calib3d core dnn features2d flann gapi highgui imgcodecs imgproc java_bindings_generator ml objdetect photo python_bindings_generator stitching ts video videoio
Disabled: world
Disabled by dependency: -
Unavailable: java js python2 python3
Applications: tests perf_tests examples apps
Documentation: NO
Non-free algorithms: NO
GUI:
Media I/O:
ZLib: build (ver 1.2.11)
JPEG: build-libjpeg-turbo (ver 1.5.3-62)
WEBP: build (ver encoder: 0x020e)
PNG: build (ver 1.6.35)
TIFF: build (ver 42 - 4.0.9)
JPEG 2000: build (ver 1.900.1)
OpenEXR: build (ver 1.7.1)
HDR: YES
SUNRASTER: YES
PXM: YES
PFM: YES
Video I/O:
DC1394: NO
Parallel framework: pthreads
Trace: YES (built-in)
Other third-party libraries:
Custom HAL: NO
Protobuf: build (3.5.1)
Python (for build): /usr/bin/python2.7
Install to: /home/kumataro/workRiscV/opencv-4.0.0/build4/install
-----------------------------------------------------------------
今後の展望(個人)
春先に画像処理と関係ないお仕事にふっとばれされてしまいましてね……。
今年はプライベートでもOpenCV触ってない事もあり、今年はOpenCVのAdvent Calenderに参加するか悩んだのですが、とりあえずえいやで参加する事にいたしました。内容が薄くて、非常に申し訳ありません。
あと、転職したい(真顔)。しかし、四十肩になってしまい辛い(超絶真顔)。