12

アクターモデルは、Gul Aghaのテクニカルレポート「アクター:分散システムでの同時計算のモデル」でうまく説明されています。

49ページで、彼は「become」コマンドについて説明しています。

become <expression>

「becomeX」を呼び出した後、アクターはすべてのメッセージを別のアクターのメールボックス(X)に転送します。

ただし、ErlangやScalaなどの言語でこれがどのように実装されているか(まったく実装されているか)はわかりません。手動でコーディングしなければならないのは何かですか?効率はどうですか?Aghaは、メッセージパッシングを使用したスタックの実装を示しています。ポップまたはプッシュが実行されるたびに、あるアクターにもう1つの転送リンクが追加されます...数十万の操作の後、そのような実装は、メッセージの転送に多くの時間を費やし、実際の作業を行わないことを期待します。優れた最適化が内部で実行されました。

だから私の質問は、Erlang、Scala(および他の言語のライブラリ)のような典型的なアクター言語で転送(または「なる」)をどのように実装するのかということです。

4

5 に答える 5

7

これはErlangに直接実装されていませんがbecome、メッセージを受信して​​別のプロセスに転送し、それ自体を呼び出す簡単な関数を作成できます。

become(Pid) ->
    receive
        Msg -> Pid ! Msg
    end,
    become(Pid).

(これの工業用強度バージョンは、信号やその他のオッズとエンドを処理する必要があるかもしれませんが、これがその本質です。)

呼び出しbecome(Pid)は、呼び出しプロセスをPid外界の観点からのプロセスに効果的に変えるでしょう。

becomeこれは、転送チェーンの成長を引き起こすための繰り返しの呼び出しで、あなたが強調する問題に対処しません。ただし、これは通常Erlangでは発生せず、Erlangのプロセスがアクターモデルにどのようにマッピングされるかはわかりません。

于 2010-07-24T13:40:07.800 に答える
4

アクターは反変の共変性者であるため、「なる」は単なる共変性です。

言い換えると、タイプTのメッセージのアクターは、基本的にタイプの関数です(T =>ユニット)。そして、これは単に関数の合成です(おそらく恒等関数を使用します)。

それはScalazで実装されています:

val a1 = actor(a => println(a))
val a2 = a1.comap(f)

アクターa2はそのメッセージにfを適用し、その結果をa1に送信します。

于 2010-07-24T23:12:33.277 に答える
4

ここでErlangに行きます。

基本的なレベルでは、2つのオプションが利用可能です。特定のプロセスの動作を変更するためだけに使用したい場合become(セクション2.1.3のリストのポイント2を参照)、別の再帰関数を使用して次のループを呼び出すだけです。

loop(State) ->
     receive
          {normal, Msg} -> loop(State);
          {change, NewLoop} -> NewLoop(State)
     end.

NewLoop高階関数であると仮定すると、{change, NewLoop}最初に関数を実行しているプロセスにメッセージを送信するたびに、その定義としてloop/1使用されます。NewLoop

2番目のオプションは、プロセスをプロキシとして機能させる(および動作を変更する)オプションです。これは、マルセロカントスが提案したものと似ています。プロセスループを作成し、メッセージを新しいメッセージに転送する(コードを盗む)だけです。

become(Pid) ->
    receive
        Msg -> Pid ! Msg
    end,
    become(Pid).

理論的には、これは論文が求めることを行います。ただし、実際には、実際のErlangシステムで2番目のオプションを使用することにはリスクがあります。2つのプロセス間の通信では、メッセージに送信者のプロセスIDを「スタンプ」し、応答に受信者のプロセスIDをタグ付けすることがよくある概念です。次のメッセージの交換を行うことができます(これはコードではなく、単なる手書き表記です)。

A = <0.42.0> <-- process identifier
B = <0.54.0>,
A: {A, "hello"},
B: {B, "hi"},
A: {A, "how are you?"}.
B: {B, "Fine!"}.

したがって、Aからのメッセージを期待する場合は、Bなどのパターンを使用することで、これらにのみ一致させることができ{B, Message}ます。転送されたメッセージの場合、このアドレス指定スキームは無効になり、単に壊れます。

別の方法は、参照(make_ref())をアドレス指定スキームとして使用して、返されるPidの上にあるメッセージを照合することです。これにより、2つの異なるエンティティを使用して、アドレスと識別子としてのPidの使用が分離されます。

アドレス指定が安全であっても、別の問題があります。プロセスの依存関係です。名前付きプロセス、クラッシュプロセス、モニターなどはどうなりますか?クライアントプロセスには、通知なしに何も問題がないことを確認するために、モニター、リンクなどがすべて設定されている場合があります。ルーティングプロセスを変更して出口信号をトラップして転送することにより、物事をより安全にすることができるはずです。

loop(State) ->
     receive
          {normal, Msg} -> loop(State);
          {become, Pid} ->
              process_flag(trap_exit, true), % catch exit signals as messages
              link(Pid),                     % make it so if one process crashes, the other receives the signal
              become(Pid)
     end.

become(Pid) ->
    receive
        {'EXIT', Pid, killed} -> exit(self(), kill);  %% uncatchable termination
        {'EXIT', Pid, normal} -> ok;                  %% die normally too
        {'EXIT', Pid, Reason} -> exit(Reason);        %% die for the same reason as Pid
        Msg -> Pid ! Msg                              %% forward the message
    end,
    become(Pid).

Pidこのテストされたコードは、最初のプロセスに依存するプロセスがで表されるものと同じエラーメッセージを受け取りbecome(Pid)、ルーティングをかなり透過的にするため、より安全であるはずです。ただし、これが実際のアプリケーションで長期的に機能することを保証するものではありません。

のようなことを表現して実行することは可能であり、概念的には十分に単純ですがbecome、Erlangの標準ライブラリは、2番目のユースケースを念頭に置いて実際には考えられていませんでした。実際のアプリケーションでは、現在存在するすべてのErlangアプリケーションで広く使用されている最初の方法のみをお勧めします。2つ目はまれであり、問​​題を引き起こす可能性があります


*become/1 *最後の例での関数の呼び出し?MODULE:become(Pid)は、将来のホットコードの読み込みに関連する潜在的なクラッシュを回避するためのものである可能性があります。*

于 2010-07-25T13:59:44.627 に答える
3

Aghaの論文「Actors:A Model of Concurrent Computation inDistributedSystem」の12ページ(私が持っているPDFコピーの26ページ)を見てください。「become」は彼のアクター言語であり、アクターの新しい動作である#2を指定する方法です。メッセージを別のアクターに転送することは、考えられる多くの新しい動作の1つにすぎません。

Scalaアクターでは、転送動作が必要な場合は、Erlangと基本的に同じボートに乗っていると思います。内部的には、Scalaの「react」と「reactWithin」はbecomeのように機能します。これは、reactブロックによって定義される部分関数がアクターの新しい動作であるためですが、類似性が意図的なものであるかどうかはわかりません。

ほとんどの(すべて?)「アクター」実装は、ヒューイットのアクターモデルおよびアガのアクター言語からかなり大きく逸脱しています。IIRCは、アガの言語で俳優の行動を指定することからの言語の部分は、チューリング完全ではありません。アクターの構成を検討する場合にのみ、言語全体がチューリング完全になります。アクターモデルと現在のアクターフレームワークの関係は、SmallTalkのオブジェクト指向とC++のオブジェクト指向の関係のようなものだと思います。いくつかの概念の移転と同様の用語がありますが、詳細では、それらは非常に非常に異なります。

于 2010-07-24T17:38:20.090 に答える
3

Akkaのアクターには「HotSwap」の概念があり、既存のメッセージハンドラーを置き換える新しいPartialFunctionをアクターに送信できます。前のものは記憶され、復元することができます。詳細については、 http: //doc.akkasource.org/actorsで「hotswap」を検索してください。

于 2010-07-25T15:02:13.533 に答える