8
задач (task level parallelism), но иногда его
еще называют функциональным
параллелизмом или параллелизмом по управлению. Его реализация сводится к
распределению заданий по узлам и обеспечению синхронности происходящих
процессов.
Альтернативный тип параллелизма называют параллелизмом данных
(data parallelism), который попадает в категорию «один поток команд, много
потоков данных» (Single Program Multiple Data, SPMD). Реализация SPMD
предполагает, что сначала данные должны быть каким-то образом
распределены
между процессорами, обработаны, а затем собраны. Эту
совокупность операций можно назвать map-reduce, как принято в
функциональном программировании, хотя точнее было бы split-aggregate, то
есть разбиение и сборка, но привилось первое.
Возможны различные способы
реализации SPMD.
Реализация SPMD требует выделения ведущей части кода, ее называют
Master или Manager (далее менеджер), и подчиненных ей частей Worker (далее
исполнитель). Менеджер «раздает» задания исполнителям и потом их собирает.
До появления MapReduce эта модель рассматривалась как малоперспективная
из-за наличия «бутылочного горла» на тракте обмена между множеством
исполнителей и одним менеджером. Создание MapReduce разрешило эту
проблему и открыло возможность для обработки огромных массивов данных с
использованием архитектуры SPMD.
Допустим, что следует решить простейшую задачу: обработать массив,
разбив его на подмассивы. В таком случае работа менеджера сводится к тому,
что он
делит этот массив на части, посылает каждому исполнителю
положенный ему подмассив, а затем получает результаты и объединяет их
(рисунок 1). В функцию исполнителя входит получение данных, обработка и
возврат результатов менеджеру. Распределение
нагрузок может быть
статическим (static load balancing) или динамическим (dynamic load balancing).
Парадигма создана по мотивам комбинации map и reduce в функциональном
языке программирования Липс. В нем map использует в качестве входных
параметров функцию и набор значений, применяя эту функцию по отношению
к каждому из значений, а reduce комбинирует полученные результаты.
Канонический пример приложения, написанного с помощью MapReduce
это процесс, подсчитывающий, сколько раз различные
слова встречаются в
наборе документов:
// Функция, используемая исполнителями на Map-фазе
// для обработки пар ключ-значение из входного потока
void map(String name, String document):
// Входные данные:
// name - название документа
// document - содержимое документа
for each word w in document:
EmitIntermediate(w, "1");