2011-06-24 5 views
7

いくつかのCPUバウンドタスクを怠る必要があるとします。たとえば、私は4つのCPUを持っている場合、私はおそらく、キュー上で待機しているキューを4~5ワーカースレッドの固定サイズのスレッドプールを作成し、タスクをキューに入れます。 Javaでは、このメカニズムを実装するのにjava.util.concurrent(たぶんThreadPoolExecutor)を使うことができます。ScalaアクターでCPUバインドタスクを実行していますか?

Scalaの俳優でどのように実装しますか?

+0

Scalaアクターまたは並列コレクションを試しましたか?彼らはすでに異なるCPUにワークロードを配布することができます。より多くのコントロールが必要な場合は、Akkaを調べることができます。 – Fabian

答えて

9

すべてのアクターは基本的にスレッドのスケジューラーによって実行されます。スケジューラは、あなたのコア数に大まかに結合したアクターを実行するスレッドプールを作成します。これは、あなたがちょうどあなたが実行し、スカラ座への残りの部分を残しておく必要がありますタスクごとに俳優を作成できることを意味します

ここでの欠点は、タスク数、タスクごとにスレッドを作成するコストに依存さ
for(i <- 1 to 20) { 
    actor { 
    print(i); 
    Thread.sleep(1000); 
    } 
} 

かもしれませんスレッドがJavaであまり安価ではないので、かなり高価なものになります。労働者の俳優の有界プールを作成し、メッセージングを経由して、それらにタスクを分散する

簡単な方法は、のようになります。

import scala.actors.Actor._ 

val numWorkers = 4 
val pool = (1 to numWorkers).map { i => 
    actor { 
    loop { 
     react { 
     case x: String => println(x) 
     } 
    } 
    } 
} 

for(i <- 1 to 20) { 
    val r = (new util.Random).nextInt(numWorkers) 
    pool(r) ! "task "+i 
} 

我々は複数のアクターを作成したい理由は、単一の俳優プロセスからです一度に1つのメッセージ(つまりタスク)のみを使用できるため、複数のタスクを作成する必要があります。

サイドノート:デフォルトのスケジューラは、I/Oバインドタスクの場合に特に重要になります。この場合、スレッドプールのサイズを間違いなく変更する必要があります。詳細については、Explore the Scheduling of Scala ActorsScala actors thread pool pitfallという2つの良いブログ記事があります。

これで、AkkaはActorsのより高度なワークフローのツールを提供するActorフレームワークであり、実際のアプリケーションで使用することになります。あなたはより多くの情報のためのドキュメントhereを確認することができるように

import akka.actor.Actor 
import Actor._ 
import akka.routing.{LoadBalancer, CyclicIterator} 

class TaskHandler extends Actor { 
    def receive = { 
    case t: Task => 
     // some computationally expensive thing 
     t.execute 
    case _ => println("default case is required in Akka...") 
    } 
} 

class TaskRouter(numWorkers: Int) extends Actor with LoadBalancer { 
    val workerPool = Vector.fill(numWorkers)(actorOf[TaskHandler].start()) 
    val seq = new CyclicIterator(workerPool) 
} 

val router = actorOf(new TaskRouter(4)).start() 

for(i <- 1 to 20) { 
    router ! Task(..) 
} 

あなたは、負荷分散の異なる種類を(CyclicIteratorは、ラウンドロビン分布である)ことができます:ここではタスク実行(ランダムではなく)ロードバランシングです。

2

まあ、通常はしません。俳優を使用することの魅力の一部は、俳優があなたのためにそのような詳細を処理することです。

しかし、あなたはそれを管理しなければならない場合は、Actorクラスの保護されたschedulerメソッドをオーバーライドして、適切なISchedulerを返す必要があります。 scala.actors.scheduler packageおよびスケジューラに関するActor traitのコメントも参照してください。

関連する問題