本日は
アドベントカレンダー $N=9$ の記事です.
Distributed.jl とラズパイを使って分散計算をさせます.MPI を使ってラズパイによるスーパコンピュータを作る試みはいくつか記事が存在しますが,この記事はその Julia 版だと思ってください.
手元にラズパイがなくても,複数の計算機がなくても一台のマシンでサンプルコードは実行できます.ですので気軽にご覧ください.
準備したもの(ハードウェア周り)
- ラズパイ5 8GB
- 今回は 8 台用意しています.予算に応じて増減してください
- 周辺機器としてはSDカード(OSを入れるため必須)
- CPUを冷やす冷却ファン(あると良い)
- スイッチングハブ
- ラズパイと作業するマシンを同じネットワークに繋げるために用います
- LANケーブル
- ラズパイとスイッチングハブを繋ぐものなので短めでもいいかもしれません
- ラズパイクラスタ用の台
- これは必須ではないですが,Amazon で「ラズパイ5 クラスタ」みたいなので検索すると出てきます.あると管理がしやすい+映えます
- 作業マシン
- ラズパイに命令するための作業マシンです.普段用いているパソコンのことです
準備したもの(ソフトウェア)
- Raspberry Pi Imager
- ラズパイ(ハードウェア)に刺すSDカードに Raspberry Pi OS を入れるために必要です.
今回はラズパイに SSH 接続できれば十分なので 64 bit の Lite 版で良いです.
ユーザ名は各ラズパイで共有しておいてホスト名は
rpi5-1, rpi5-2, rpi5-3, ..., rpi5-8
のように番号を振っておきます.各自で特定のラズパイにSSH接続しやすい・管理しやすいネーミングがあればそれでOKです.
作業マシンから ssh <設定したユーザ名>@rpi5-1.local のように接続できるか確認しておきます.このフェーズが成功しないと何もできません.各マシンに Juliaup で Julia をインストールしておきます.
作業マシンに tmux を入れて各ラズパイに一斉に命令を送信する.
これはオプションですが作業マシンに tmux を入れておくと各々のラズパイに同じコマンドを送信できるので楽です.
下記のようなシェルスクリプトを作業マシンで持っておいて bash session5.sh としておくだけです.
# もっといいスクリプトがあれば教えてちょ
#!/usr/bin/env bash
SESSION="rpi"
USER="terasaki" # ここは各自のユーザ名にすること
HOSTS=(rpi5-{1..8}.local) # 0:rpi5-1 … 7:rpi5-8
# ── 0. セッション作成(既存なら再利用)
tmux new-session -Ad -s "$SESSION" "ssh ${USER}@${HOSTS[0]}"
# ── 1. 上段を 4 分割 (HOSTS[1]–[3])
for i in {1..3}; do
tmux split-window -h -t "$SESSION":0.0 \
"ssh ${USER}@${HOSTS[$i]}"
done
# ── 2. 下段左端を作成 (HOSTS[4])
tmux split-window -v -p 50 -t "$SESSION":0.0 \
"ssh ${USER}@${HOSTS[4]}"
# ── 3. 下段をさらに 3 分割 (HOSTS[5]–[7])
tmux select-pane -t "$SESSION":0.4 # ★ 下段左端を「現在ペイン」に
for i in {5..7}; do
tmux split-window -h "ssh ${USER}@${HOSTS[$i]}"
done
# ── 4. 2×4 に整列 & 同期入力
tmux select-layout -t "$SESSION":0 tiled
tmux set-window-option -t "$SESSION":0 synchronize-panes on
tmux attach -t "$SESSION"
下記のようになります.作業マシンでは julia と入力するだけで一斉に Julia の REPL が起動します.
今回はラズパイがCPUリソースを使ってるか確認するために htop コマンドを使うだけしか使いません.
計算をする
以下作業マシンで作業します.ラズパイはJuliaを事前にインストールしておき, htop でリソースを管理しておけばOKです.
Distributed.jl を使って計算をしてみましょう.
作業マシンで下記のようなスクリプトを用意します.
using Distributed
if nworkers() == 1
@info "Start machines..."
p = addprocs(
[
# 各自のマシンに置き換えること
("terasaki@rpi5-1.local", 4),
("terasaki@rpi5-2.local", 4),
("terasaki@rpi5-3.local", 4),
("terasaki@rpi5-4.local", 4),
("terasaki@rpi5-5.local", 4),
("terasaki@rpi5-6.local", 4),
("terasaki@rpi5-7.local", 4),
("terasaki@rpi5-8.local", 4),
],
# 各自が設定したラズパイのユーザ名
dir = "/home/terasaki",
# Julia がある場所
exename = "/home/terasaki/.juliaup/bin/julia",
)
@info "Machines launched!"
end
# 円周率を計算する
function calcπ(N)
cnt = @distributed (+) for a = 1:N
s = 0
for b = 1:N
s += ifelse(gcd(a, b) == 1, 1, 0)
end
s
end
prob = cnt / N / N
√(6 / prob)
end
@info "Setup done"
function main()
@info "Start processing..."
N = 100
@info "Warm up"
@info N
output = @time calcπ(N)
for N in [100, 1000, 10_000, 5 * 10_000, 100_000]
@info N
output = @time calcπ(N)
@show output
end
end
@info "Run main() manually"
if abspath(PROGRAM_FILE) == @__FILE__
main()
end
作業マシンの Julia を起動して include("gcd_pi.jl") を実行します.Run main() manually というログが出るまでしばらく待ちましょう.これはラズパイ側で Julia プロセスが起動するのを待つためです.
REPL で main() を入力して実行します!
ラズパイ側は CPU がフル稼働している様子がわかります.
手元の環境では N = 100000 で 12 秒ほどで終了しました.
手元のマシン(M2 Max 12 core) をぶん回しても24秒ほどかかってるのでラズパイ8台の構成のほうが早く処理が終わってることがわかります.
まとめ
ラズパイを8台用意し Julia + Distributed.jl で分散計算をさせました.




