Параллельный подсчет с использованием функционального подхода и неизменяемых структур данных?

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

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

Что было бы правильным, но также практичным чисто функциональным способом, используя для этого неизменяемые структуры данных?




Ответы (2)


Общий подход к функциональному анализу наборов данных состоит в том, чтобы разделить набор данных каким-либо разумным образом, для документа вы можете разделить его на разделы в зависимости от размера. т.е. четыре потока означает, что документ разделен на четыре части.

Затем поток или процесс выполняет свой алгоритм для каждого раздела набора данных и генерирует выходные данные. Все выходные данные собираются вместе, а затем объединяются. Например, для подсчета слов набор подсчетов слов сортируется по слову, а затем каждый список просматривается с использованием поиска тех же слов. Если это слово встречается более чем в одном списке, подсчеты суммируются. В итоге выводится новый список с суммами всех слов.

Этот подход обычно называют картой / сокращением. Шаг преобразования документа в количество слов - это «карта», а объединение результатов - «сокращение».

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

Кроме того, функциональное программирование позволяет таким системам, как Spark, динамически создавать потоки, поскольку границы изменений четко определены. Вот почему вы можете написать одну цепочку функций в Spark, а затем просто использовать серверы, не меняя код. Чистые функциональные языки могут делать это в общем случае, делая каждое приложение по сути многопоточным.

Одна из причин, по которой функциональное программирование так популярно, - это возможность прозрачной и безопасной многопроцессорной обработки.

person Grant BlahaErath    schedule 27.06.2018
comment
Хорошо, поэтому на этапе отображения каждый процесс просто обрабатывает свою собственную часть данных, используя свою собственную отдельную структуру данных. Для подсчета слов это может быть хэш-карта, а поскольку процесс не зависит от других, хеш-карта на самом деле не должна быть неизменной, поскольку только один поток когда-либо обновляет ее, верно? Но этот подход также требует, чтобы был способ перефразировать операцию, которая будет выполняться в режиме сокращения карты. Хотя это можно сделать очевидным способом для подсчета слов, я уверен, что есть другие задачи, где это сложно или доказуемо невозможно? - person jpp1; 12.07.2018
comment
да. Не все проблемы поддаются map-reduce, но интересно находить умные способы сделать это. Например, вычисление хэша не может выполняться параллельно, потому что каждое вычисление зависит от предыдущего, но данные могут быть разбиты на блоки, а хэши записаны в каталог, который затем хешируется. Там увеличивается скорость создания за счет более поздних сравнений. - person Grant BlahaErath; 14.07.2018

Мутация и состояние вредны для параллелизма только в том случае, если изменяемое состояние совместно используется несколькими потоками для связи, потому что очень сложно спорить о нечистых функциях и методах, которые незаметно уничтожают некоторую общую память параллельно.

Одна из возможных альтернатив - использование передачи сообщений для связи между потоками / участниками (как это делается в Akka) и создание («достаточно чистых») структур функционального анализа данных, таких как Apache Spark, поверх него. Известно, что Apache Spark хорошо подходит для подсчета слов в большом корпусе документов.

person Andrey Tyukin    schedule 25.06.2018
comment
Спасибо! Я понимаю, что проблема изменяемых структур данных возникает из-за их совместного использования, но меня также интересует более теоретический вопрос о том, как на самом деле может выглядеть чисто функциональный подход? Если все, что у меня есть, - это функции и значения, и я хочу реализовать таким образом пример параллельного подсчета слов, как мне это сделать? - person jpp1; 26.06.2018