2011-06-24 17 views
7

Farz edelim ki, CPU'ya bağlı birkaç görevi yerine getirmek zorundayım. Örneğin 4 CPU'um varsa, muhtemelen bir kuyrukta bekleyen 4-5 çalışan iş parçacığı sabit boyutlu bir iş parçacığı havuzu oluşturur ve görevleri sıraya koyardım. Java'da bu mekanizmayı uygulamak için java.util.concurrent (belki ThreadPoolExecutor) kullanabilirim.CPU'ya bağlı görevleri Scala oyuncularıyla mı yürütüyorsunuz?

Scala oyuncularıyla nasıl uygularsınız?

+0

Scala Aktörleri veya paralel koleksiyonları denediniz mi? İş yükünü zaten farklı CPU'larda dağıtabilirler. Daha fazla kontrole ihtiyacınız varsa Akka'ya bir göz atabilirsiniz. – Fabian

cevap

9

Tüm oyuncular temel olarak başlık altındaki bir programlayıcı tarafından çalıştırılan iş parçacıklarıdır. Zamanlayıcı, çekirdek sayınıza kabaca bağlanan aktörleri çalıştırmak için bir iş parçacığı havuzu oluşturur. Bu sadece size yürütmek ve Scala gerisini bırakmak gerekir görevin başına bir aktör oluşturmak anlamına gelir:

burada dezavantaj görevlerin sayısının, her görev için bir iş parçacığı oluşturma maliyetine bağlı olduğu
for(i <- 1 to 20) { 
    actor { 
    print(i); 
    Thread.sleep(1000); 
    } 
} 

may Java'da threadlar çok ucuz olmadığı için oldukça pahalı olun.

şey gibi olurdu mesaj yoluyla kendilerine görevleri dağıtmak ardından işçi aktörlerin sınırlı bir havuz oluşturmak ve basit bir yolu: Biz oyuncuların çokluğu oluşturmak istiyorum

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 
} 

nedeni tek aktör süreçler nedeniyle Bir kerede sadece bir mesaj (yani görev), görevleriniz için paralellik elde etmek için birden fazla oluşturmanız gerekir.

Bir yan not: Varsayılan zamanlayıcı, G/Ç ilişkili görevler söz konusu olduğunda, özellikle de bu durumda iş parçacığı havuzunun boyutunu değiştirmek isteyeceğinizden özellikle önem kazanır. Bu konuda ayrıntılara giren iki iyi blog yazısı: Explore the Scheduling of Scala Actors ve Scala actors thread pool pitfall.

Bununla birlikte, Akka, Aktörlerle daha gelişmiş iş akışları için araçlar sağlayan bir Aktör çerçevesidir ve gerçek bir uygulamada kullanacağım şey budur. Eğer daha fazla bilgi için dokümanlar here kontrol edebilirsiniz böylece

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(..) 
} 

Sen, Yük Dengeleme farklı (CyclicIterator yuvarlak robin dağılımıdır) sahip olabilir: Burada görev uygulamakla (yerine rastgele yerine) bir yük dengeleme.

2

Genellikle yapmazsınız. Oyuncuları kullanmanın cazibesinin bir kısmı, sizin için bu tür ayrıntıları ele almalarıdır.

Ancak, bunu yönetmek konusunda ısrar ederseniz, uygun bir IScheduler dönmek için Actor sınıfında korumalı scheduler yöntemini geçersiz kılmanız gerekir. Ayrıca, scala.actors.scheduler package ve zamanlamalarla ilgili Actor trait'daki yorumlara bakın.

İlgili konular