Параллельные коллекции в Scala 2.9 и Актерах - PullRequest
11 голосов
/ 10 апреля 2011

Хорошо, это может быть довольно глупый вопрос, но каково преимущество использования параллельных коллекций в рамках актера? То есть, если я имею дело только с одним сообщением из почтового ящика актера, есть ли необходимость в параллельном сборе? Параллельные коллекции и актеры являются взаимоисключающими? Каков вариант использования, который включал бы оба?

Ответы [ 2 ]

15 голосов
/ 10 апреля 2011

Они решают разные проблемы.Актеры хороши в решении задач параллельных задач .В то время как параллельные коллекции хорошо решают проблемы параллельных данных .Я не думаю, что они являются взаимоисключающими - вы можете использовать параллельные коллекции в актерах и параллельные коллекции, содержащие акторов.


Редактирование - быстрый тест: даже что-то простое, например, цикл уведомления актера, дает преимущества.

В следующем коде мы регистрируем миллион актеров в реестре актеров, который должен уведомить их о событии.

Непараллельный цикл уведомлений (registry foreach {}) занимает в среднем 2,8 секунды на моей машине (4-ядерный ноутбук с частотой 2,5 ГГц).Когда используется параллельный цикл сбора (registry.par.foreach {}), он занимает 1,2 секунды и использует все четыре ядра.

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")

}
2 голосов
/ 11 апреля 2011

Библиотека акторов в Scala - это лишь один из вариантов, подходов к параллелизму, среди многих (нити и блокировки, STM, фьючерсы / обещания), и она не должна использоваться для всех видов проблем или сочетаться свсе (хотя актеры и STM могли бы многое сделать вместе).В некоторых случаях создание группы действующих лиц (работников + супервизора) или явное разбиение задачи на части, чтобы передать их в пул разветвления, слишком громоздко, и просто удобнее вызывать .par насуществующей коллекции, которую вы уже используете, и просто проходите ее параллельно, получая выигрыш в производительности практически бесплатно (с точки зрения настройки).

В целом, акторы и параллельные коллекции - это разные измеренияпроблема - акторы - это парадигма параллелизма, тогда как параллельные коллекции - это всего лишь полезный инструмент, который следует рассматривать не как альтернативу параллелизма, а скорее как расширение набора инструментов коллекций.

...