2013年4月25日木曜日

Erlangでプロセスたくさん使ってフィボナッチ数列を計算したら、too many processesとなっておこられたで御座る。

調子が悪いので

Erlangで初心者的なことをやって

自信を回復しようとしているみけです。



Erlangでのプロセス間通信


spawnという関数を用いて関数を実行すると、

その関数のプロセス識別子が取得出来ます。

そしてプロセス識別子に対して!演算子を用いることで、

プロセスに対してメッセージを送信することができます。


フィボナッチ数列の計算


ところで、Erlangでフィボナッチ数列を計算する関数は簡単に書けます。

-module(fib).
-export([fib/1]).

fib(N) when N < 2 -> 1;
fib(N) ->
    fib(N - 1) + fib(N - 2).

ところが、この関数はひとつのプロセスで実行するために、

値が大きくなると途端にパフォーマンスが低下します。

3> timer:tc(fib, fib, [10]).
{11,89}
4> timer:tc(fib, fib, [12]).
{24,233}
5> timer:tc(fib, fib, [14]).
{61,610}
6> timer:tc(fib, fib, [20]).
{1546,10946}

timer:tc関数の戻り値の一つ目の要素が実行時間(ms)です。

ガクガクって増えていっている様子がわかります。


そこで複数プロセスでフィボナッチ数列を計算する


そこで、fib:fib関数を少し修正して、

プロセス間通信する形で計算してみます。



では、試してみます。

3> timer:tc(fib, fib, [10]).
{2889,89}
4> timer:tc(fib, fib, [12]).
{5109,233}
5> timer:tc(fib, fib, [14]).
{5684,610}
6> timer:tc(fib, fib, [20]).
{132777,10946}


う〜んと、値が大きい割には、値の増え方が緩いですね。

では、40くらいだとどうなるでしょうか?

7> timer:tc(fib, fib, [10]).


結果が返ってきませんねー





あ、え、エラー…

too many processesだってw


というわけで


まあ、何が問題だったかというと、

所詮4コアしか積んでいないマシンで無数のプロセスを起動すると、

死ぬ

というわけですね。


まあ、当たり前と言っちゃ当たり前ですね。


さて、では、プロセス数を4より増やさないようにして

書いてみたのが次のやつになります。



関数fibはひとつのプロセスでやる奴。

関数cfibは二つのプロセスでやる奴。

関数ccfibは四つのプロセスでやる奴。


で、実際に時間を計測してみました。




だいたい、16〜20くらいで、複数プロセスの効果が現れていますね。






0 件のコメント:

コメントを投稿