Как Scala достигает parallelism?

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

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

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

Ответ 1

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

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

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

IO медленный, и блокировка вызывает потоки hog в то время, когда вы выполняете IO, а не используете CPU. Таким образом, ключом к получению лучшего уровня parallelism является настройка этого пула потоков:

  • Если вы выполняете только неблокирующее IO, вы можете установить его на количество ядер процессора, и вы уверены, что полностью используете свой процессор.
  • Чем больше блокируется IO, тем больше потоков вам нужно будет получать хорошие parallelism, но будьте осторожны - чем больше потоков вы используете, тем больше памяти вы будете использовать, а потоки - не самые легкие вещи в Мир.

Ответ 2

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