arm
Sphero完全ガイド book
これ面白いな。ボールがプログラミング通りに回転しながら移動する。昔に流 行ったlogoと組合せると、亀さんの代りをさせられる。
どんな原理で動いているのだろう? 直ぐに思い付くのは、重心を移動させて転がすって方法だけど、他にもあるかな?
何やらLEDの表示器が付いていたり、デジタルコンパスやら青葉無線機能が有っ たりと、周辺機器が豊富にぶら下っている。IO制御の塊なのね。こういうロボッ トを制御するCPUはarmな石だろうね。
予定調和的に、ラズパイ・ボードでも採用してるのなか。このロボット欲しい けど、床に絵を書くだけじゃ、つまらない。だったら、アレだな。
Raspberry Pi for poor man
以前に作ったarmな環境が古くなってて、emacsをコンパイルするにに必要な pkgが手に入らなくなってた。ええ、例のbytecode実行系がarmな石だと、どう なるか確認したかったんです。
そこで、下記を参考に、新しい環境を作る事にした。こちらは、容量制限を回避する方法。
Raspberry Pi のセルフビルド環境を QEMU で作る
実験なので、手間のかからない下記の方法を取 る事にした。
Raspberry Pi用バイナリをQEMUエミュレータで動かす方法(ユーザーモードエミュレーション)
起動スクリプト
sakae@usvr:~/sim/arm$ cat boot #!/bin/bash sudo mount -o offset=50331648 181113.img rootfs sudo mount -t sysfs sysfs rootfs/sys sudo mount -t proc proc rootfs/proc sudo mount -t devtmpfs udev rootfs/dev sudo mount -t devpts devpts rootfs/dev/pts sudo QEMU_CPU=arm11mpcore /usr/sbin/chroot rootfs sudo umount rootfs/dev/pts sudo umount rootfs/dev sudo umount rootfs/proc sudo umount rootfs/sys sudo umount /home/sakae/sim/arm/rootfs
とりあえずの、動作確認
sakae@usvr:~/sim/arm$ ./boot root@usvr:/# su - pi pi@usvr:~ $ uname -a Linux usvr 4.15.0-43-generic #46-Ubuntu SMP Thu Dec 6 14:45:28 UTC 2018 armv7l GNU/Linux pi@usvr:~ $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop3 1712920 1031916 575944 65% / udev 978036 0 978036 0% /dev pi@usvr:~ $ exit exit root@usvr:/# exit exit
空容量が575Mあれば、emacsの一式ぐらいコンパイルできるでしょう。(インス トールはしない積りです)
なお、piユーザーに切り替えておかないと、前世代の石になっちゃう様なんで 注意。
make emacs for arm
早速コンパイルしてみる。armを起動させると、rootfsの中にファイルシステ ムが出現するんで、rootfs/tmp あたりに、tar球を落す。ユーザーpiに取って は、空から突然降ってきた隕石みたいなものでしょう。
後は、みみっちい設定でconfigする。
pi@usvr:~/emacs-26.1 $ ./configure --with-sound=no \ --without-cairo --without-dbus --without-gconf --without-gif \ --without-gsettings --with-x-toolkit=no --without-jpeg \ --without-lcms2 \ --without-m17n-flt --without-imagemagick --without-libotf \ --without-png \ --without-toolkit-scroll-bars --without-rsvg --without-tiff \ --without-x --without-xim --without-xpm --without-xwidgets \ --with-gnutls=no
大体開発環境は初期状態ではいっているんだけど、特殊なやつは無いから入れ ろとアドバイスされたよ。
checking for library containing tputs... no configure: error: The required function 'tputs' was not found in any library. The following libraries were tried (in order): libtinfo, libncurses, libterminfo, libcurses, libtermcap Please try installing whichever of these libraries is most appropriate for your system, together with its header files. For example, a libncurses-dev(el) or similar package.
で、コンパイル
: make[1]: Nothing to be done for 'info-dir'. make[1]: Leaving directory '/home/pi/emacs-26.1' real 14m52.877s user 14m22.355s sys 0m31.999s pi@usvr:~/emacs-26.1 $ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/loop3 1712920 1365644 242216 85% / udev 978036 0 978036 0% /dev
何とかDISKも足りたようだ。
pi@usvr:~/emacs-26.1/src $ file emacs emacs: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=a97c7cbf8c32e100e72d630332ccc605385d990f, not stripped
こんな具合に完成した。よかったね。
bytecode for arm
op -= Bvarref; 274: e2411008 sub r1, r1, #8 Lisp_Object v1 = vectorp[op], v2; 278: e51b3040 ldr r3, [fp, #-64] ; 0xffffffc0 27c: e7933101 ldr r3, [r3, r1, lsl #2] if (!SYMBOLP (v1) 280: e3130007 tst r3, #7 284: 1a000005 bne 2a0 <exec_byte_code+0x280> return lisp_h_XSYMBOL (a); 288: e59f2da4 ldr r2, [pc, #3492] ; 1034 <exec_byte_code+0x1014> 28c: e0831002 add r1, r3, r2 || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL 290: e7d32002 ldrb r2, [r3, r2] 294: e202200e and r2, r2, #14 298: e3520008 cmp r2, #8 29c: 0a000082 beq 4ac <exec_byte_code+0x48c> v2 = Fsymbol_value (v1); 2a0: e1a00003 mov r0, r3 2a4: ebfffffe bl 0 <Fsymbol_value> PUSH (v2); 2a8: e51b2028 ldr r2, [fp, #-40] ; 0xffffffd8 NEXT; 2ac: e51b303c ldr r3, [fp, #-60] ; 0xffffffc4 2b0: e2844001 add r4, r4, #1 PUSH (v2); 2b4: e5a20004 str r0, [r2, #4]! NEXT; 2b8: e5541001 ldrb r1, [r4, #-1]
run temacs
pi@usvr:~/emacs-26.1/src $ ls -l | grep -- -rwxr -rwxr-xr-x 3 pi pi 29477828 Jan 25 05:56 bootstrap-emacs -rwxr-xr-x 3 pi pi 29477828 Jan 25 05:56 emacs -rwxr-xr-x 3 pi pi 29477828 Jan 25 05:56 emacs-26.1.1 -rwxr-xr-x 1 pi pi 12333480 Jan 25 05:55 temacs
これsrcの中の成果物。ハードリンクで3個出来上がってるのはいいんだけど、 容量の小さいtemacsは何者? 考えていても分らないので、走らせちゃえ。
起動した途端に、statusラインが点線のものが表われ、盛んに*.elをローディ ングしてた。*Messages*には、
Loading replace...done Loading emacs-lisp/tabulated-list...done Loading buff-menu...done Loading emacs-lisp/float-sup...done Loading vc/vc-hooks...done Loading vc/ediff-hook...done Loading uniquify...done Loading electric...done Loading emacs-lisp/eldoc...done Loading cus-start...done Loading tooltip...done Loading leim/leim-list.el (source)...done Finding pointers to doc strings...done Pure-hashed: 14449 strings, 3846 vectors, 36664 conses, 3726 bytecodes, 164 others For information about GNU Emacs and the GNU system, type C-h C-a. Loading loadup.el (source)...done
こんな記録が残っていた。そうか、temacsは裸のlispで、それに肉付けしてか ら、全体をダンプすると、emacsになるんだろう。(これ、sbcl等で、シングル バイナリーを作成する手段に使われていたな)
M-x emacs-versionすると
GNU Emacs 26.1 (build 1, armv7l-unknown-linux-gnueabihf) of 2019-01-25
gdbが使えるかと思って試したら、
(gdb) r Starting program: /home/pi/emacs-26.1/src/emacs qemu: Unsupported syscall: 26
あえなくハングした。ウブ側のプロセスを確認。
1660 pts/1 S 0:00 /bin/bash ./boot 1677 pts/1 S 0:00 sudo QEMU_CPU=arm11mpcore /usr/sbin/chroot rootfs 1678 pts/1 Sl 0:00 /usr/bin/qemu-arm-static /bin/bash -i 15855 pts/1 Sl 0:00 /usr/bin/qemu-arm-static /bin/su - pi 15858 pts/1 Sl 0:00 /usr/bin/qemu-arm-static /bin/bash 33605 pts/1 Sl+ 0:01 /usr/bin/qemu-arm-static /usr/bin/gdb emacs 33611 pts/1 Tl 0:00 /usr/bin/qemu-arm-static /home/pi/emacs-26.1/src/ema
33605のプロセスを殺せばいいかと思ってやってみたら、chroot自身が終了し ちゃって、ウブのプロンプトに戻ってしまった。gdbは封印しておかなければ!!
comp
こうして、無事にarmな環境が出来たけど、どれぐらいの性能が出るのか確認 したくなる。そこでベンチマークですよ。
感覚的に、amd64でのemacs作成が2分少々、対してarm32では15分弱なんで、ざっ くり8倍ぐらいの違いが有るかなと予想。
ELISP> (benchmark-run (tarai 12 6 0)) (0.859854004 0 0.0)
これ、ウブなamd64機での結果。
ELISP> (benchmark-run (tarai 12 6 0)) (7.848208675 0 0.0)
今度は、armな石のシュミレータ。予想は的中しましたな。ああ、tarai.elcは、 amd64の方で作ったものを、そのまま利用。armな石は、エンディアンがインテ ル系と違うのかな。だとすれば、石の壁を乗り越えている訳だ。 まるで、一度作れば何処でも動くjavaみたいだな。
emacsって、インストールしなくても、普通に使える様になってるの ね。~/.emacs.dは、勝手に作られていたよ。この中に、init.elを突っ込んで おけば、俺様仕様で動いてくれるだろう。
ふと、armな環境がマルチCPUって事を思い出した。Windows10のタスクマネー ジャーでCPUの働きぶりを見たらどうなるのだろう?
結果は、4CPUが動いていた。ウブは、vmwareで2CPUを割り当てているんだけど、 コア数を意味してるのかな?1コアに2論理プロセッサなんで、モニター上では、 全ての石が動いてると報告されるのか。
ウブ側のemacsでやってみると、cpu2,cpu3の負荷が急上昇してる。つられて、 cpu0,cpu1の負荷も上がるけど、cpu2,3側程では無いという結果。
場合によってバラツクが有るなあ。そもそも、taraiって、手分けして実行す るような代物なのかなあ。副作用が無い関数なんで、手分けしようと思えば、 手分けできるだろうけど。
at debian
32Bitなマシンにもarmな環境を作ってみた。こちらは、容量無制限方式。 ウブな方は、環境が181113.imgの中に閉じ込められた(クロージャ方式)ものだ けど、debianな方は、親のDISKの容量制限に引っ掛かるだけ(無理にこじつけ ると、ダイナミック方式だな)
起動スクリプトは、こんな感じにした。
debian:~$ cat sim/arm/boot #!/bin/bash sudo mount -t sysfs sysfs rootfs/sys sudo mount -t proc proc rootfs/proc sudo mount -t devtmpfs udev rootfs/dev sudo mount -t devpts devpts rootfs/dev/pts sudo /usr/sbin/chroot rootfs /bin/bash sudo umount rootfs/dev/pts sudo umount rootfs/dev sudo umount rootfs/proc sudo umount rootfs/sys
さて、これで何を試そう。ラズパイもどきのarmな石と言っても、動いてしま えば、インテル系のそれと見分けがつかないからね。今更emacsを入れても悩 が無いしね。そんな事で、ヤバそうな、gaucheを試してみる。最近新らしいの が出たしね。
なにが懸念されるかと言うと、一つは、gc。これひょっとしてインテル系に特 化していないか? もう一つは、扱える数値の範囲問題。果たして予想が的中 するか、やってみる。(吾ながら、動機が不純だなあ)
bignum.c: In function ‘bignum_add_int’: gauche/priv/arith.h:88:15: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] (c) = ((r)<(x) || ((r)==(x) && ((y)>0||(c)>0)))? 1 : 0; \ ^ bignum.c:616:17: note: in expansion of macro ‘UADD’ UADD(br->values[i], c, 0, 0); ^~~~ gauche/priv/arith.h:88:15: warning: comparison of unsigned expression < 0 is always false [-Wtype-limits] (c) = ((r)<(x) || ((r)==(x) && ((y)>0||(c)>0)))? 1 : 0; \ ^ bignum.c:620:13: note: in expansion of macro ‘UADD’ UADD(br->values[i], c, 0, y);
微妙な警告だなあ。shiroさんの頭の中を覗いてみたい衝動。これarmな石に特 有な警告かなあ。コンパイルが成功したら、是非 make checkしておこう。
コンパイルの進行状態は、やっとgcエリアをクリアして、本体にかかって来た。 果てしなく時間がかかるなあ。過去の記憶では、emacsを作るより時間がかかっ たはずだからね。
: make[1]: Nothing to be done for 'all'. make[1]: Leaving directory '/home/pi/Gauche-0.9.7/examples' cd src; /usr/bin/make -s static real 76m37.225s user 75m12.064s sys 0m27.900s
やっと終わった。やっぱり時間がかるね。当社比、10倍は遅いですって感じか な。
はて、インストールしなくても、普通に使えたかな?
pi@debian:~/Gauche-0.9.7/src $ ./gosh *** ERROR: cannot find "gauche/interactive" in ("/usr/local/share/gauche-0.97/site/lib" "/usr/local/share/gauche-0.97/0.9.7/lib") Stack Trace: _______________________________________ WARNING: Encountered an error during loading gauche.interactive. Falling back to basic REPL. gosh> (cons 1 2) (1 . 2) gosh> (define (d n) (* n n)) d gosh> (d 1111111111111111111111111111111111111111) 1234567901234567901234567901234567901234320987654320987654320987654320987654321
replの便利な機能は、使えないけど、取りあえず動くな。
make[1]: Leaving directory '/home/pi/Gauche-0.9.7/src' Total: 19601 tests, 19601 passed, 0 failed, 0 aborted. make[1]: Entering directory '/home/pi/Gauche-0.9.7/src' make[1]: Leaving directory '/home/pi/Gauche-0.9.7/src' real 19m38.386s user 17m58.348s sys 0m13.920s
暇にまかせてcheckしてみた。問題なしって事で安心しましたよ。と、言いつ つ、普通に使う分には、x86だろうとarmだろうと違いは無し。只の自己満足以 外の何物でも有りません。
Goroutine
上で並行処理の話が出てきた。並行と言えばgolangだなと、馬鹿の一つ覚えで、 goroutineが頭に浮かんだ。例のtaraiで試してみようと、go taraiを複数記述 したけど、実行時間は、0秒。これはおかしいってんで、調べてみたら、待合 せには、特殊な方法が必要と、下記のURLに載ってた。
そんな訳で、下記を作りあげてみた。
package main import "fmt" import "sync" import "time" func tarai(x, y, z int) int { if x <= y { return y } else { return tarai(tarai(x-1, y, z), tarai(y-1, z, x), tarai(z-1, x, y)) } } func main() { start := time.Now() var wg sync.WaitGroup for i := 0; i < 4; i++ { wg.Add(1) go func(i int) { fmt.Printf("%d\n", i) tarai(14, 7, 0) wg.Done() }(i) } wg.Wait() ex := time.Since(start) fmt.Printf("%f\n", ex.Seconds()) }
ちょっと効果の程をvbox上のFreeBSDで確認していみる。CPU数は、2つの環境だ。
make -k go run tarai.go 0 3.515730
一つの盥だと、3.5秒と出た。四つの盥をリレーさせると、4倍の時間がかかる はずだけど、上の仕掛けで、並列に走るはず。
make -k go run tarai.go 3 0 1 2 7.125511
短かい時間で盥競争は終了した。負荷をうんと重くして競争を始め、タスクト レーで、CPUの利用率を確認すると58%になってた。CPUパワーが全開 になっていないのね。
Windows10に入れているgoでやってみる。
sakae@atom:/mnt/c/Users/sakae/go/src/tarai$ make go.exe run tarai.go 0 1.860035 sakae@atom:/mnt/c/Users/sakae/go/src/tarai$ make go.exe run tarai.go 2 1 3 0 3.310808
随分速いな。負荷をかけると、CPU利用率が100%まであがった。全力疾走なら ぬ、全力漕ぎなんですな。
物はついでなんで、チープな石のセレロン版i386でやってみる。
debian:tarai$ make go run tarai.go 0 4.670436 debian:tarai$ make go run tarai.go 3 0 1 2 18.620675
どう頑張ってもCPUは一つなんで、順番に実行するから、4倍の時間がかかるん だな。
taraiはニッチな業界であるLisp国の競技だったけど、これで国際舞台へデビュー だな。来るオリンピックでは、エキシビジョンで、盥漕ぎ競争が行なわれるに 違いない。勿論、バックグランドミュージックと言うか、お囃子は、佐渡おけ さで決まりかな。
まてまて、youは何しに日本へ、って番組で、たらい漕ぎ競争が取り上げられ ていた記憶があるぞ。ちょいと調べてみる。
横手市の増田って所が有名なのね。知りませんでした。