web-dev-qa-db-ja.com

私の俳優モデルの説明は正しいですか?

私が理解した場合、アクターモデルはオブジェクトモデルと同じですが、いくつかの違いがあります。

  1. すべてのオブジェクトはそれ自身の個別のスレッドを生成し、何千ものオブジェクトがある場合でも問題にはなりません。
  2. アクターは、関数を呼び出して戻り値を取得するのではなく、メッセージを送受信することで対話します。
  3. そのモデルに違反していない場合、アプリは競合状態のリスクなしに同時実行性を最大限に活用します。
  4. OOアクターを使用して実行できるすべてのことを行うことができますが、ここ数年でコーディングしたすべてがOOベースでしたが、移行差し迫っています。

たとえば、3Dベクトルクラス/アクターを定義し、2つのインスタンスを作成して、それらに対して合計操作を呼び出す必要があるとします。

目的のオブジェクト:

class V3d {
   constructor V3d(x,y,z) //bla
   float x,y,z;
   function sum(V3d b) 
   { 
      return V3d(x+b.x,y+b.y,z+b.z); 
   }
}

//using:
mySum = V3d(1,2,3).sum(V3d(3,2,1)) //creates 2 instances, sum, returns instantly
drawPoint(mySum) //uses the result

俳優モデル:

actor V3d 
{
    constructor V3d(x,y,z) //bla
    float x,y,z;
    loop 
    {
       receive 'sum',b:V3d :
           send(caller,'sumResult',V3d(x+b.x,y+b.y,z+b.z))
    }
 }

//using:
send(V3d(1,2,3),'sum',V3d(3,2,1)) //creates 2 instances, send to the first one a request to sum with the second one

loop 
{
   receive 'sumResult',result:
      drawPoint(result) //receives result and draws it
}

それですか?それとも私は完全に間違っていますか?

13
WindScar

短い答えはノーです、それは正しくありません。

  1. 合理的には正しく開始されます(各アクターは少なくとも潜在的に独立したスレッドとして実行されます)が、その後大部分はRailsから外れます。多くのスレッドを適切に機能させるmodelについては何もありません-それは実装次第です。多くの場合、多数のスレッドを作成することの容易さは、効率的なスレッド化を実現するための実装に圧力をかけます。少なくともモデルが気にする限り、アクターとオブジェクトの類似点はほとんど偶然です。 「オブジェクト」は、コードとデータをどのように組み合わせるかについてかなり具体的な意味を持っています。アクターは通常、コードとデータの両方を含みますが、それらがどのように組み合わされるかについてはほとんど意味がありません(外部の世界に見える唯一のデータがメッセージであるという事実以外)。

  2. 相互作用を説明する通常の方法は、メッセージ送信です(はい)。私は便利な引用はありませんが、C++仮想関数のようなメカニズムがメッセージ送信と同型であることをかなり前に誰かが証明しました(仮想関数は通常実装されているため、vtableへのオフセットを使用していますが、代わりにメッセージのテーブルにオフセットを送信しましたが、効果は同じです)。

  3. それほど単純ではありません。コピーが見つかれば、ヘンリーベイカー(名前を覚えていない他の人と一緒に)がActorモデルのデータの整合性に必要なルールについての論文を書きました。

  4. 「ベター」はせいぜい非常に主観的です。一部の問題は本質的に高度に並列であり、実際には多数の本質的に自律的なエンティティが関与しており、主に非同期である最小限の対話を伴います。その場合、俳優モデルは非常にうまく機能します。他の問題については、実際にはそうではありません。いくつかの問題は本質的にほぼ完全にシリアルです。他のものは並行して実行できますが、それらのアクション間の密接な同期が必要です(たとえば、基本的にSIMDに似たモードで、一度に1つの命令を実行しますが、各命令は多数のデータ項目に作用します)。アクターモデルを使用してこれらのタイプの問題の両方を解決することは確かに可能ですが、そのような問題の場合、多くの場合、見返りにほとんどまたはまったく利益を得られないために、かなりの追加作業が必要になります。

12
Jerry Coffin

1に関して:私は単一の(スレッド化された)スレッド化されたActorモデルのアプリケーションで作業したので、これが示唆する大きなスレッド数を無視することはかなり可能です。私の知る限り、スレッドは決して軽量オブジェクトではないので、使用しているアクタの数によっては、アクタごとに1つ持つことはおそらく望ましくありません。

3:プログラミングロジックが原因で、アクターモデル化されたシステムで競合状態が発生する可能性があると確信していますか?

4:「より良い」とは?私の経験では、非同期ロジックは同期のものよりも読みにくい場合があります。たとえば、上記の例では、どの操作がどの結果の原因であるかがわからないため、実行する追加のメッセージ追跡があります。それが追加され、他のメッセージがロジックに含まれると、コードの意図はいくつかの送信/受信機能に広がります。

それをすべて言っても、私はアプリケーションの上位層で使用するアクターモデルの大ファンです。依存関係を追加することは、関数を追加することよりも少し難しいので、分離を容易にすることができます。また、Java言語よりも高いレベルでの経験はあまりありません。他のパラダイムは、より基本的な方法で非同期性をサポートしている可能性があります。

2
tugs