アクターモデルの説明は正しいですか?


13

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

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

したがって、たとえば、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
}

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


軽量のアクターまたはマイクロエージェントまたはデータフローコンポーネントは、必ずしも独自のスレッドを使用しません。:-)次の用語を確認してください:アクターベースのプログラミング、エージェントベースのプログラミング、データフローベースのプログラミング。それらは非常に似ていますが、異なる制約があります。
ああ

回答:


12

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

  1. 合理的に正しい状態で開始します(各アクターは少なくとも独立したスレッドとして実行される可能性があります)が、その後はほとんどレールから外れます。については何もありません多くのスレッドをうまく機能させるモデル -それは実装次第です。せいぜい、多くのスレッドを簡単に作成できるため、効率的なスレッド化を実現するために実装に圧力がかかります。少なくともモデルが気にする限り、アクターとオブジェクトの類似性はほとんど偶然です。「オブジェクト」は、コードとデータをどのように組み合わせるかについてかなり具体的な意味を持ちます。通常、アクターにはコードとデータの両方が含まれますが、それらがどのように組み合わされるかについてはほとんど意味しません(外部から見えるデータはメッセージだけであるという事実を除く)。

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

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

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


アクターの数とスレッドの数の間に関係はありません。アクターモデルが保証しているのは、特定のインスタンスが一度に1つのスレッドのみで操作されるため、アクターは既にスレッドセーフであり、内部で同期およびロック戦略を使用する必要がないということです。
ロブクロフォード

@RobCrawford:これは、アクターモデルでデータの一貫性を確保する1つの(かなり簡単な)方法です。ヒューイット/ベイカーの論文は、別のスレッドで実行されているアクターの複数のコピーなど、より多くの可能性をカバーしています私がそれを書いたときに皮肉なこと)。
ジェリーコフィン

メッセージの非同期性はモデルの重要な要素を通過していませんか?これにより、本質的に同期的な仮想関数呼び出しで同型になるのを確実に防ぐことができます。それとも、区別は何らかの観点からは無関係ですか?
ボーイシー

2

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

3:プログラミングロジックが原因で、アクターモデルのシステムで競合状態が発生する可能性はかなり高いと思いますか?

4に関して:「より良い」定義?私の経験では、非同期ロジックは同期的なものよりも読みにくい場合があります。たとえば、上記の例では、どの操作がどの結果に責任があるのか​​わからないため、追加のメッセージ追跡が必要です。それが追加され、他のメッセージの入出力がロジックに含まれると、コードの意図は複数の送信/受信機能に広がります。

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


#1に関して:「スレッド」は多くのことを指します。通常、OSスレッドはかなり重いです。しかし、少数のOSスレッド内で数百、数千、さらには数百万の「スレッド」の実行を内部的に処理する言語ランタイムがあります。いくつかの実装では、そのようなモデルは明らかに数十のコアにスケールアップします(最近のGHCバージョンが32コアでうまく機能するというステートメントを見てきました)。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.