Raspberry Pi を使う | たけおか ぼちぼち日記

たけおか ぼちぼち日記

思いついたらメモ


Raspberry Pi、かわいいよ、Raspberry Pi。というわけで、
おうちで Raspberry Pi を動かし始めて、はや数ヶ月。

先日は、グランフロント大阪の大阪イノベーションハブ(OIH)で開かれた
『英国発テクノロジーが世界を変える Raspberry Piが開くGlobal Innovation』という会で、
Raspberry Pi財団創始者の Eben Uptonさんと、
パネルセッションもやってきた。(ステージ右端のピンクシャツがあたくし)




この会は英国総領事が挨拶するわ、大阪市の人が挨拶するわ、で非常にお堅い面々が運営される会でありましたよ。




あたくしは、Raspberry Pi を、
東京のアパートのゲートウェイとし、
また、3nodeのクラスタ計算機として計算ができるようにしてみている。



Raspberry Piを、おうちのゲートウェイとする話。

あたくしのアパートは、インターネットがおまけでついている。
しかし、集合住宅で非常にありがちなように、NATが入っている。
そのNAT設定は、いじりようがない。(お願いする仕組みさえ無い)
なので、NATルータを設定して、port forwardingすることは不可能。

しかし、インターネット小僧の端くれとして、
自宅サーバに外からloginできないなど、許されない、というか気持ち悪い。

あたくしは、固定IPアドレスを持つ、自分のインターネット・サーバ(www.takeoka.org)は持っている。
そこで、www.takeoka.org と Raspberry Piの間でVPN を張ることにした。
Raspebrry Pi から、www.takeoka.org に VPN を張らせておけば、どんなIPプロトコルでも使用可能だ。

今回は、極めて安直に、PPP over ssh にした。
(PPTP とかの方がいいかも知れないが、www.takeoka.orgで試したことが無いので…)
たけおか ぼちぼち日記-gateway fig


以下、具体的な手順

以下では、固定IPアドレスのサーバを serv とする。
serv は、FreeBSDである。
Raspberry Piを raspiとする。
raspiは、Linuxである。

1)
raspiで、

raspi% ssh-keygen -f vpn1key

を実行。
vpn1key (秘密鍵) と vpn1key.pub(公開鍵) ができる。
raspi から、servに vpn1key.pub を送っておく。

raspi% scp vpn1key.pub serv:/tmp



2)
serv で root になって、(BSDは、rootのshellは、cshである)
serv に "vpn1" などというアカウントを作る。
そして、 ~vpn1/.ssh/authorized_keys にraspiの公開鍵を登録する。


serv# mkdir ~vpn1/.ssh
serv# cd ~vpn1/.ssh
serv# touch authorized_keys
serv# chmod 600 authorized_keys
serv# cat /tmp/vpn1key.pub >> authorized_keys
serv# cd ~vpn1
serv# chown -R vpn1 .ssh






3)
raspiから、serv にvpn1 として、パスワード無しでloginできることを確認する。

raspi% ssh vpn1@serv

初回だけ、ホストを登録するか? などと聞かれる。
二度目以降に、何も聞かれずに ssh で login できることを確認する。


4)
serv に vpn1 としての login 時に、pppd を起動するようにする。

vpn1 のlogin shell は、/bin/csh。(cshは、login時に ~/.loginを実行する)
serv上で、root 権限で、~vpn1/.login を編集し、その内容を下記とする。


pppd 115200 local proxyarp nocrtscts 192.168.254.1:192.168.2.12 nodetach noauth idle
300

logout


その後、

serv# chown vpn1 ~vpn1/.login

をやっておく

ここで、
192.168.254.1は、serv側のアドレス、
192.168.2.12 は、raspi側のアドレス。

PPPのインターフェースに与えるアドレスは、
serv側はプライベートIPアドレスで、かつ、アパート内LANと被らないようにする。
raspi側も、アパート内LANと被らない方がうまくいく。



5)
raspiから、ppp を試してみる。

raspiでrootになり、pppdを入れる。


raspi% sudo bash
raspi# apt-get install ppp


raspiから、ppp over sshを試す。

raspi# /usr/sbin/pppd pty 'ssh -t -t vpn1@serv -o Batchmode=yes -i vpn1key ' linkname vpn local noauth persist connect-delay 2000 idle 3000 updetach


上記の vpn1key は、秘密鍵 vpn1key ファイルのフルパスで記述する。


raspi# ifconfig


とやって、

:
ppp0 Link encap:Point-to-Point Protocol
inet addr:192.168.2.12 P-t-P:192.168.254.1 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:7 errors:1 dropped:0 overruns:0 frame:0
TX packets:7 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
RX bytes:63 (63.0 B) TX bytes:73 (73.0 B)
:

と、ppp0 などの接続が確立され、アドレスが割当たっていれば、成功。


raspi% ping 192.168.254.1

で、ping 応答が serv から来る。


serv% ping 192.168.2.12

で、ping 応答が raspi から来る。

以上ができれば、serv から、raspi(192.168.2.12)に ssh ができる。

serv% ssh 192.168.2.12




6)
raspiの
/usr/local/bin/vpn-serv
などのファイルを下記の内容でつくる。


#!/bin/csh
echo vpn-takeoka.org
/usr/sbin/pppd pty 'ssh -t -t vpn1@serv -o Batchmode=yes -i vpn1key ' linkname vpn local noauth persist connect-delay 2000 idle 3000 updetach


raspiの /etc/rc.localの
末尾に、

sleep 30;
sh /usr/local/bin/vpn-serv &

を加えると、自動起動。

「sleep 30」は、eth0など、通常のインターネット接続が安定するのを待つための、待ち時間。
eth0がdhcpなどの時は、それが成功する十分な時間を待つべき。




Raspberry Piで、MPI計算

Webでググると、Raspberry Piで、MPI計算している人は多い。
特に、Python で計算している人が多そうだ。
それもよかろう。

あたくしは、C と mpich2 でやった。
Raspberry Piは、3台。

たけおか ぼちぼち日記-cluster-picture

たけおか ぼちぼち日記-Cluster fig

ノードごとにローカルのUSBメモリを持たせ、ext4 ファイルシステムにしているが、深い意味は無い。
マスタ・ノードでは、USBメモリを /usr1 にマウントし、exportし、
スレーブ・ノードはマスタの USBメモリを /usr1 に、NFSマウントしている。
マスタでもスレーブでも、/usr1 上の、同じファイルは、同じパスで見えるようにする。
MPIを使用するときの常套手段だ。

マスタ・ノードのUSBメモリに、プログラムの実行バイナリ(例えば、/usr1/take/devel/test)やデータを置き、
マスタ・ノードから mpiexec をすると、スレーブでも、そのバイナリ(/usr1/take/devel/test)が実行される。

本当は、管理コストを無くすため、スレーブノードは、NISでユーザ管理をすべきだが、今はNISは使っていない。
(たまに、スレーブ・ノードを切り離して、単独でよそへ持っていくことがあるので、各ノードごとに/etc/passwdで管理)


具体的には次のとおり

0)
ノードのIPアドレスが、変わると色々と面倒くさいので、今は、
各ノードの /etc/rc.local 中に
ifconfig eth0 ホスト名
として、静的にIPアドレスを設定している。
/etc/hosts に、自機の名前と IPアドレスは記述しておく。

これも、管理コストを下げるために、マスタ・ノードかどこかで、dhcp サーバを動かして、
dhcpの Ethernetアドレス-IPアドレス対応表を一元管理するべきだろう。
(今は、3台なので、まぁ気にしない)


1)
マスタ・ノードは、NFSサーバをインストールする。
ついでに、NFSクライアントもインストールする。自分自身で、自分をサーバとしたNFS マウントができるか試せると、
便利であるから。

マスタ・ノードのホスト名は、node00



node00# apt-get install nfs-kernel-server
node00# apt-get install nfs-common portmap rpcbind


ここで、「portmapの代わりに rpcbindを使ってるよ」と言われるが、気にしない。
(何も追求していない)

NFSサーバの起動は次のとおり


node00# service rpcbind start
node00# service nfs-common start
node00# service nfs-kernel-server start



NFSサーバを自動的に起動するには、次のとおり


node00# update-rc.d nfs-kernel-server enable
node00# update-rc.d nfs-common enable
node00# update-rc.d rpcbind enable



node00# rpcinfo -p

で、NFSが起動して rpc を使用しているか、確認できる。

また、NFSの情報は、

node00# nfsstat -s

などで、確認できる。



/etc/exportsに

/usr1 (rw,sync,no_subtree_check)

だけの行を書く。
本当は、アクセス制御を指定すべきだが、自宅LANで、完全に安全であるので、
「なんでもあり」にしておく。
(きまぐれに、他のホストからNFSマウントすることも多いので)


node00# exportfs -av

として、/usr1 を exportする。


node00# exportfs
/usr1 <world>

とやって、export状態が確認できる。


ここで、

node00# mount node00:/usr1 /mnt

とやり、短い時間で終了すると成功。


node00# mount
/dev/root on / type ext4 (rw,noatime,data=ordered)
:
node00:/usr1 on /mnt type nfs4 (rw,relatime,vers=4.0,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.128,local_lock=none,addr=192.168.1.128)


node00# df
ファイルシス 1K-ブロック 使用 使用可 使用% マウント位置
rootfs 1804128 984964 727516 58% /
:
/dev/sda1 15192472 1771496 12649244 13% /usr1
node00:/usr1 15192512 1771520 12649280 13% /mnt


/mnt に cdして、ファイル読み書きができることを確認する。
それが終了したら、


node00# umount /mnt

とやって、NFSマウントは解除する。


2)
スレーブ・ノードのNFS クライアント。

インストールは、下記のとおり。
スレーブ・ノードは、node01。


node01# apt-get install nfs-common rpcbind
node01# service rpcbind start
node01# service nfs-common start

node01# update-rc.d rpcbind enable
node01# update-rc.d nfs-common enable


NFSマウントの開始は次のとおり

node01# mkdir /usr1
node01# mount node00:/usr1 /usr1


/etc/fstab に、下記の行を追加

node00:/usr1 /usr1 nfs noauto,noatime 0 0


NFSを本格運用するならば、上記の「noauto」は記述せず、ブート時に自動マウントするように設定する。

※ブート時に自動マウントを行わせると、NFSサーバが異常なときに、NFSクライアントはブートが成功せず、
ブート・シーケンスが終了しない。
(soft mount だと、なんとかなるはずだが、RaspberryPiでは試していない)
NFSサーバ異常の時も、シングルユーザ・モードでなら起動可能だが、
私は、Raspberry Piにコンソールを繋いでいないので、シングルユーザ・モードで立ち上げることが、
極めて面倒である。
また、私は、スレーブ・ノードを、単独で持ち出すので、NFSの自動マウントはしない。


3)
MPIのインストール
mpich2-1.4.1p1 を使用した。(よそでも実績があるので)

ディスク容量に余裕があるところで、以下を行う。

以下では、/usr1 に余裕があり、mpich2 を /usr1 に実体を置くことにする。が、通常は、/usr/local/mpich2/にあると思ってアクセスできるようにする。


node00% wget http://www.mcs.anl.gov/research/projects/mpich2/downloads/tarballs/1.4.1p1/mpich2-1.4.1p1.tar.gz
:
node00% tar xvzf mpich2-1.4.1p1.tar.gz
:
node00% cd mpich2-1.4.1p1
node00% ./configure --prefix=/usr/local/mpich2
:
node00% make
:

node00# mkdir /usr1/mpich2
node00# ln -s /usr1/mpich2 /usr/local/
node00# make install

以上で、/usr/local/mpich2/ (実体は、/usr1/mpich2/)に、mpichがインストールされる。


MPIのプログラムは、普通に持ってきてコンパイルすれば問題なく動く。

コンパイラとして、mpicc を使用する。
mpicc のオプションに 「 -mfpu=vfp 」を指定する。
(そうしなければ、vfp(浮動小数点ハードウェア)用のコードが生成されないような気がした)
リンク時には、.o ファイルの後に -lm を指定して、math ライブラリを探すようにさせる。



% mpiexec -f hostファイル -np プロセス数 実行バイナリ

とする。

ここで、hostファイルの内容は

node00

(node00 で 1プロセスだけ起動)
とか、

node00:2

(node00 の 2プロセス起動)
とか、

node00:2
node01:2
node02:2

(node00,01,02 で各々2プロセスを起動)
と書く。

マスタ・ノード(node00)からは、ssh を使用して各ノードでバイナリを起動する。
よって、node00から、各スレーブ・ノードへは、パスワード問い合わせ無しでssh を可能にするべきである。
その設定は、上の PPP over ssh のあたりに書いたとおり、
node00の ssh公開鍵を、各ノードの ~/.ssh/authorized_keys に入れることで行う。

各ノードは、マスタのホームディレクトリを、共有するようにしていれば、
authorized_keys の編集は、すべて一ヶ所でできるので、便利だろう。
(私は、x86 のクラスタ・マシンでは、そうしている)




Raspberry Piの単体(1core)で、いわゆるマイクロ・ベンチマークを行った結果

Dhrystoneの結果
Dhrystones per Second: 1501501.5
(Pentium III P3 733程度の性能 ※ Linux Benchmarks による)

Whetstoneの結果
% cc -mfpu=vfp -O4 whetstone.c -lm
% ./a.out -c 100000
Loops: 100000, Iterations: 1, Duration: 32 sec.
C Converted Double Precision Whetstones: 312.5 MIPS

クロック 700MHzの ARM11 なので、妥当な性能であろう。



-- 2013/JUN/02 23:30 追記 --

無線LANは、
BUFFALO WLI-UC-GNM2T が非常に調子いい。
WiFi をスキャンしたりする時も、この WLI-UC-GNM2T を使うのがいいらしい。



-- 2013/JUN/02 23:30 追記 --
動画再生

% omxplayer 動画ファイル
とやると、動画が再生できる。
X Windowとは、無関係に描画している。

ハードウェアにアクセラレータ入っているので、かなり高解像度で、ビットレートの高い動画も、
楽々と再生できる。



-- 2013/JUN/03 01:11 追記 --

Clisp を使う
Common Lisp も Gnu Emacsも使える。

% sudo apt-get install clisp
% apt-get install emacs23
とやればよい。

emacsの中から、clispと対話するには、
GNU Common Lispを使う の、
末尾の方の「4. GCLをEmacsと組み合わせて使う」を参照。



-- 2013/JUN/02 23:30 追記 --

NetBSD

Raspberry Piでも、NetBSDが動く。
ftp.NetBSD.orgのえびじゅんさんのところ
から、イメージを取得する。
2GB以上のSDカードを準備する。

# gunzip < 2013-03-04-netbsd-raspi.img.gz|dd of=/dev/sdc1 bs=1mb conv=sync
(Ubuntuの時)

このSDカードを、Raspberry Piに刺して起動するだけ。
login: が出たら、
root (パスワード無し)でログイン。

# xinit
とやると、普通に X Window が動作する。
Ethernet も普通に動作している。