2011-04-09 18 views
11

Bien, esta podría ser una pregunta bastante tonta, pero ¿cuál es el beneficio de usar colecciones paralelas dentro de un marco de actor? Es decir, si solo estoy tratando con un mensaje a la vez del buzón de un actor, ¿existe incluso la necesidad de una recolección paralela? ¿Las colecciones paralelas y los actores son mutuamente excluyentes? ¿Qué es un caso de uso que involucre a ambos?Colecciones paralelas en Scala 2.9 y actores

Respuesta

15

Ellos resuelven diferentes problemas. Los actores son buenos resolviendo task parallel problems. Si bien las colecciones paralelas son buenas para resolver data parallel problems. No creo que sean mutuamente excluyentes: puede usar colecciones paralelas en actores y colecciones paralelas que contienen actores.


Editar - prueba rápida: Incluso algo tan simple como un agente de notificación beneficios de bucle.

En el siguiente código registramos un millón de actores con un registro de actores que tiene que notificarles de un evento.

El bucle de notificación no paralelo (registry foreach {}) demora un promedio de 2.8 segundos en mi máquina (notebook de 4 núcleos a 2.5 GHz). Cuando se utiliza el ciclo de recopilación paralelo (registry.par.foreach {}), demora 1.2 segundos y utiliza los cuatro núcleos. biblioteca

import actors.Actor 

case class Register(actor: Actor) 
case class Unregister(actor: Actor) 
case class Message(contents: String) 

object ActorRegistry extends Actor{ 
    var registry: Set[Actor] = Set.empty 

    def act() { 
    loop{ 
     react{ 
     case reg: Register => register(reg.actor) 
     case unreg: Unregister => unregister(unreg.actor) 
     case message: Message => fire(message) 
     } 
    } 
    } 

    def register(reg: Actor) { registry += reg } 

    def unregister(unreg: Actor) { registry -= unreg } 

    def fire(msg: Message){ 
    val starttime = System.currentTimeMillis() 

    registry.par.foreach { client => client ! msg } //swap registry foreach for single th 

    val endtime = System.currentTimeMillis() 
    println("elapsed: " + (endtime - starttime) + " ms") 
    } 
} 

class Client(id: Long) extends Actor{ 
    var lastmsg = "" 
    def act() { 
    loop{ 
     react{ 
     case msg: Message => got(msg.contents) 
     } 
    } 
    } 
    def got(msg: String) { 
    lastmsg = msg 
    } 
} 

object Main extends App { 

    ActorRegistry.start 
    for (i <- 1 to 1000000) { 
    var client = new Client(i) 
    client.start 
    ActorRegistry ! Register(client) 
    } 

    ActorRegistry ! Message("One") 

    Thread.sleep(6000) 

    ActorRegistry ! Message("Two") 

    Thread.sleep(6000) 

    ActorRegistry ! Message("Three") 

} 
+0

Gracias por la respuesta. Puedo ver que uno * PUEDE * usar colecciones paralelas dentro de los actores, pero no parece que sería más ventajoso que usar una colección regular en este caso. La idea de usar una colección paralela que contenga actores, por otro lado, parece una cosa útil. Me gusta esa idea. Gracias por darme algo en que pensar ... –

+1

Gracias por crear un código de prueba, ¡eso es genial! Realmente lo aprecio. –

+0

@Bruce. Observe que hay otra oportunidad de usar colecciones paralelas aquí; el código anterior toma alrededor de 12 segundos para hacer el ciclo de inicio. Si paralelizamos que tarda aproximadamente 4 segundos ((1 a 1000000) .par.foreach {i => ...}). –

2

Actores en Scala es sólo una de las opciones, se acerca a la concurrencia, entre muchos (hilos & cerraduras, MCI, futuros/promesas), y se supone que no debe ser utilizado para todo tipo de problemas, o ser combinable con todo (aunque los actores y STM podrían hacer un buen negocio juntos). En algunos casos, configurar un grupo de actores (trabajadores + un supervisor) o dividir explícitamente una tarea en porciones, para alimentarlos al grupo fork-join, es demasiado engorroso, y es mucho más sencillo llamar al .par en una cuenta existente. colección que ya está utilizando, y simplemente recorrerlo en paralelo, obteniendo un beneficio de rendimiento casi gratis (en términos de configuración).

En general, los actores y colecciones paralelas tienen diferentes dimensiones del problema: los actores son un paradigma de concurrencia, mientras que las colecciones paralelas son solo una herramienta útil que no debe verse como una alternativa de concurrencia, sino como un aumento del conjunto de herramientas de colecciones.

+0

Gracias por su perspectiva sobre esto. Que tiene sentido. –

Cuestiones relacionadas