Как в Scala достигается параллелизм?

Я прохожу курс по распределенным системам, и мы должны сделать наш проект на Scala. Наш инструктор сказал нам, что Scala хороша в том смысле, что он использует несколько ядер для выполнения вычислений и использует параллелизм для решения проблем при интеграции с моделью акторов.

Это теоретический вопрос. Я изучил некоторые основы модели акторов с использованием Akka, и мой вопрос заключается в том, что при программировании пользователь должен предоставлять детали компилятору, чтобы различные акторы работали на нескольких ядрах, или Scala позаботится об этом и использует несколько ядра для различных актеров?

Вкратце, у меня вопрос: когда мы объявляем несколько субъектов, использующих библиотеки Akka в Scala, компилятор Scala автоматически использует мощность многоядерного процессора для распределения различных субъектов между ядрами, или программист должен предоставить какие-то данные для этого?


person nitinsh99    schedule 13.09.2013    source источник


Ответы (2)


TL; DR: с конфигурацией по умолчанию в Akka вам не нужно ничего делать, чтобы получить хороший параллелизм для большинства случаев использования.

Более длинный ответ: Актеры в Akka работают на Диспетчере и этот Dispatcher имеет ExecutionService, который обычно представляет собой пул потоков. Количество потоков настраивается разработчиком, но по умолчанию оно в 3 раза превышает количество ядер ЦП на машине (см. default-dispatcher.parallelism-factor здесь в эталонной конфигурации).

В любой момент времени каждое ядро ​​ЦП может запускать Актера, использующего один из этих потоков, поэтому, если у вас есть количество потоков в ExecutionService диспетчера, которое равно количеству ядер на вашем ЦП, вы сможете воспользоваться этим преимуществом. всех ваших ядер. Причина, по которой в конфигурации по умолчанию установлено в три раза большее количество ядер, заключается в компенсации блокировки ввода-вывода.

Ввод-вывод выполняется медленно, и при блокировании вызовов потоки блокируются, когда вы выполняете ввод-вывод, а не используете ЦП. Таким образом, ключом к достижению наилучшего уровня параллелизма является настройка этого пула потоков:

  • Если вы выполняете только неблокирующий ввод-вывод, вы можете установить его на количество имеющихся у вас ядер ЦП и быть уверенным, что вы в полной мере используете преимущества своего ЦП.
  • Чем больше вы блокируете ввод-вывод, тем больше потоков вам понадобится для сохранения хорошего параллелизма, но будьте осторожны - чем больше потоков вы используете, тем больше памяти вы будете использовать, а потоки - не самые легкие вещи в мире.
person theon    schedule 13.09.2013
comment
Спасибо за быстрый ответ. Означает ли это, что диспетчер AKKA позаботится о параллелизме, а от пользователя требуется только указать количество участников (или потоков) во время программирования? - person nitinsh99; 13.09.2013
comment
Создайте столько Актеров, сколько вам нужно. Количество потоков - это то, что вам нужно настроить для наилучшего параллелизма. Если вы выполняете только неблокирующий ввод-вывод, установите его на количество ядер ЦП, которое у вас есть. Чем больше вы блокируете ввод-вывод, тем больше потоков вам понадобится для обеспечения хорошего параллелизма. Но да, с конфигурацией по умолчанию вам ничего не нужно делать, чтобы получить хороший параллелизм для большинства случаев использования. - person theon; 13.09.2013

Ответ theon довольно хорош, но я просто хотел бы отметить, что акторы - не единственный способ добиться параллелизма в Scala. Если вам не нужно управлять состоянием, Futures, как правило, является более простым способом выполнения параллельных вычислений. Вы просто оборачиваете каждый фрагмент кода, который может выполняться независимо от других, в вызове фабричной функции Future, а затем можете составлять / преобразовывать результаты каждого фрагмента (также параллельно), используя вызовы map, flatMap, fold и т. Д. , или с for пониманиями. Все, что вам нужно настроить, - это ExecutionContext как implicit val, и если вы уже используете Akka, вы можете использовать тот же, который используют ваши акторы, или вы можете использовать предварительно настроенное глобальное значение по умолчанию.

person reggert    schedule 16.09.2013
comment
Хорошая точка зрения. Стоит также упомянуть параллельные коллекции. Просто добавьте в область видимости ExecutionContext, как вы упомянули, а затем измените любые вызовы с coll.map, coll.filter и т. Д. На coll.par.map и coll.par.filter для мгновенного параллелизма. - person theon; 24.09.2013