Nonperturbative loopiness

作文練習帳

Raspberry Pi clusterでMathematicaを使う

雑記です。コロナ騒ぎでいつも使っていた計算機の使用に"面倒なこと"が増えてしまったので、「自前でクラスター作るチャンスだ!」と思い、試しに試行錯誤した記録を残します。とりあえず方法を知っておくことが目的だったので、Raspberry Pi 4 Model B/4GB *2個で遊んでみました。

参考になるかもしれない文献は

です。

Background

Raspberry Pi は安価な手のひらサイズのコンピュータです。素晴らしいことに、Raspberry PiはWolframと提携していて、無料でMathematicaを使うことができます! *1 一方で、Mathematicaは普通にライセンスを入手するととても高い *2

このような状況にあるので、raspberry pi clusterでmathematicaを使うと低コストでmathematicaの重い計算を回せるかもしれない。

準備

揃えるもの

まずは動くraspberry piを欲しい数だけ揃えます。n個準備したいなら、

を準備する。*5

ここでは方法を紹介するに留めるので、とりあえず2つ準備します。

VNC: リモートで操作する

n個マウス・キーボード・モニターが準備できればそれでいいのですが、それはむしろコストがかかるので、リモートでPCやタブレットで操作できるようにしておきます。 基本的には

  • IP addressを固定する。
  • Raspberry PiVNCを有効にする。
  • Real VNCをクライアントに導入する。

をすればよいです。これに関してはよい解説が容易に見つかると思うので、詳しくは省略します。

Passwordless SSH

Mathematicaがデバイスを超えてコマンドを実行するために、SSHの準備をしておきます。*6

クライアント側 (使う方) で公開鍵を生成し、それをサーバー側 (使われる方) に認証させます。相互に認証させ、行き来できるようにします。 あるデバイスを一つ決め (master)、そのデバイスからそのほかの全てのデバイスにログインできるようになっていれば良さそうです。

操作は次の通りです。

  1. クライアント側でsshキーを作成: "ssh-keygen"を実行 *7 。この際パスワードは入力しない。
  2. 続けて、home/pi/.sshディレクトリに公開鍵ファイル id_rsa.pubが生成されていることを確認。*8
  3. サーバー側のhome/pi/.sshディレクトリ (無ければ作る) に "authorized_keys" というファイルを作成
  4. クライアント側で生成したid_rsa.pubの内容をさっき作ったauthorized_keysにコピー。id_rsa.pubに書いてある「ssh-rsa 何たらかんたら」を (2つ目以降なら改行して) authorized_keysにぺたぺた貼り付けます。 *9
  5. これで準備は完了です。繋がるかテストするには、サーバー側をrebootしたあと、クライアント側から"ssh -i .ssh/id_rsa pi@(サーバー側のipアドレス)"を実行してつないでみるとよいです。 *10
  6. 上記の操作を、全てのデバイスに対して、自分自身を除く全てのデバイスの公開鍵をauthorized_keysに書き込むまで繰り返します。 あるデバイス (master) の公開鍵をauthorized_keysに書き込むまで繰り返します。

こうしてSSHの準備が整いました。

Mathematica Remote Kernel Configuration

Mathematicaがremote kernelを使えるようにします。操作は次の通りです。

  1. Mathematicaを立ち上げ、FrontEndTokenExecute["PreferencesDialog"]を実行します。
  2. Parallel tab -> Remote Kernels -> Enable Remote Kernels -> Add Hostと進みます。

f:id:nonpert_loop:20200630174241p:plain
Remote Kernelタブ

  1. Host nameにRemoteで使用するraspberry piipアドレスを入力する。 -> Kernelを4にする。他はデフォルトで良い。-> Enableにチェックを入れる。

f:id:nonpert_loop:20200630175354p:plain
Add hostの設定 (ここでは192.168.0.3のraspberry piを使用することにする)

これで終わりです。諸々めんどくさいことは自動でやってくれる!うれしいね!

動かしてみる。

便利なコマンドにParallelCombineなるものがあります。 

reference.wolfram.com

AbsoluteTimingで時間を測ってあげて、とりあえず素数を104個求めてあげましょう。構成はRaspberry Pi 4 Model B/4GB *2個です。 比較のため、local kernelでの評価も行ってあげます。なのでMathematica

AbsoluteTiming[ParallelCombine[Prime,Range[10000]]]

AbsoluteTiming[Prime[Range[10000]]]

を行ってみます。すると並列化した方は0.283021 sec、並列化してない方は0.01479 secかかりました。並列化しない方が速い!悲しい!

並列化による通信コストを頭に置いておかないといけないかもしれません。

これで終わってしまうのも悲しいので、素数を106個求めてあげました。結果は並列化した方は2.97868 sec、並列化してない方は7.05872 secで、ちゃんと2倍程度早くなっていました。

f:id:nonpert_loop:20200630194833p:plain
実行した結果。なお$KernelCountでアクティブなカーネルを数えることができる。

Mathematicaの並列計算について、コマンドは公式ドキュメント

reference.wolfram.com

を参考にしてください。だいたいParallelize[]関数で全部やってくれそうな気がします。 *11

こうして複数デバイスでの並列化をすることができました。

感想

RPi4は普通に一台で強いので、たくさん買えば結構重い計算を投げることができそうです。 でもRPi 4で遊んでると保冷剤がすぐ溶けてしまう。熱い。

*1:https://www.wolfram.com/raspberry-pi/

*2:https://www.wolfram.com/mathematica/pricing/

*3:記事を書いている時点で最も高スペック。スペックは Raspberry Pi 4 Model B specifications – Raspberry Pi 参照。記事を書いている途中で8GBのモデルが発売されてしまいました……

*4: Raspbianを入れておく。例えば https://www.kkaneko.jp/tools/raspbian/raspbian_install.html

*5: 探すのがめんどくさい人には、代理店によるスターターキットがある。 https://raspberry-pi.ksyic.com/main/index

*6: 例えば、 https://qiita.com/hinemoss/items/2bdc2293c84bc1001214 などの解説があります。

*7: デフォルトではRSA 2048bit; RSAでない他の暗号化方式を採用する場合は-t optionを使う。

*8: 同時に生成されているid_rsa秘密鍵なので扱いには注意すること。

*9:セキュリティが不安なら、/etc/hosts.denyと/etc/hosts.allowを編集するなりして、接続可能なipを指定するとよい。

*10:接続しても接続した感がつかめないですが、exitしてみるとどのipからログアウトしたかわかる。

*11:AbsoluteTiming[ParallelCombine[Prime,Range[10000]]]の代わりにAbsoluteTiming[Parallelize[Prime[Range[10000]]]]を実行してもほとんど同じ時間で結果を返してもらえる。