全体の概要
# | プロセス | 処理 |
---|---|---|
1 | 計算 | 受け入れ可能になったら :ready メッセージを送る |
2 | スケジューラ | やることがあれば :fib メッセージを送る |
3 | 計算 | フィボナッチ数を計算し、結果を :answer メッセージとして送る |
4 | スケジューラ | やることがなくなれば :shutdown メッセージを送る |
5 | 計算 | :shutdown を受信したらプロセスを終了する |
計算プロセス
FibSolver.fib(scheduler)
:ready
メッセージ送信:fib
メッセージ受信
フィボナッチ数を計算し、:answer
メッセージ送信:shutdown
メッセージ受信
プロセス終了
スケジューラプロセス
Scheduler.run(num_processes, module, func, to_calculate)
num_processes
の数だけ以下の処理を繰り返し、num_processes
分の計算プロセスを生成
spawn(module, func, [self])
- 各プロセスごとに
schedule_processes
を実行
Schedule.schedule_processes(processes, queue, results)
processes
: 計算プロセスのリストqueue
: フィボナッチ数計算時の引数のリスト
引数が37
=> n = 37のときのフィボナッチ数を求める
:ready
メッセージ受信queue
の要素数 > 0
{next | tail } = queue
とする
next
を:fib
メッセージで送信
schedule_processes(processes, tail, results)
を実行
=>
schedule_processes
に渡すprocesses
の要素数は変わらないが、queue
の要素数は減っていくqueue
の要素数 = 0
:shutdown
メッセージを送信process
の要素数 > 0
processes
から該当するプロセスを削除し、schedule_processes
を実行process
の要素数 = 0
result
を「フィボナッチ数計算時の引数の降順」に並べて返す
=>
処理が終了
:answer
メッセージ受信
受け取った結果をresults
に詰めてschedule_processes
を実行
ガード節に length(list) > 0
を使うとすべての要素を走査してしまうので、パターンマッチを使うべき
[_ | _]
でパターンマッチqueue != []
goh@goh% elixir spawn/fib.exs
[{37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}, {37, 24157817}]
# time (s)
1 6.00
2 3.18
3 3.06
4 3.06
5 3.15
6 3.32
7 3.00
8 3.05
9 3.19
10 3.20