Вопрос

Я понимаю, насколько легко распараллелить Map — каждый компьютер/процессор может работать только с небольшой частью массива.

Можно ли распараллелить сокращение/foldl?Кажется, что каждое вычисление зависит от предыдущего.Можно ли его распараллелить только для определенных типов функций?

Это было полезно?

Решение

Если основная операция сокращения является ассоциативной *, вы можете играть с порядком операций и местностью. Поэтому у вас часто есть древовидная структура в фазе «сбора», поэтому вы можете сделать это за несколько проходов в логарифмическом времени:

a  +  b  +  c  +  d
 \   /       \   /
 (a+b)       (c+d)
     \       /
   ((a+b)+(c+d))

вместо (((a + b) + c) + d)

Если ваша операция является коммутативной, возможна дальнейшая оптимизация, поскольку вы можете собирать данные в другом порядке (это может быть важно для выравнивания данных, когда эти операции, например, являются векторными операциями)

[*] ваши реальные желаемые математические операции, а не операции с эффективными типами, например, с плавающей точкой.

Другие советы

Да, если оператор ассоциативный. Например, вы можете распараллелить суммирование списка чисел:

step 1: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
step 2:   3   +   7   +   11  +   15
step 3:       10      +       26
step 4:               36

Это работает, потому что (a + b) + c = a + (b + c), т. е. порядок выполнения дополнений не имеет значения.

Проверьте фазу объединения в Hadoop

http://wiki.apache.org/hadoop/HadoopMapReduce

Не уверен, о какой платформе / языке вы думаете, но вы можете распараллелить операторы типа Reduce следующим образом:

// Original
result = null;
foreach(item in map) {
    result += item;
}

// Parallel
resultArray = array();
mapParts = map.split(numThreads);
foreach(thread) {
    result = null;
    foreach(item in mapParts[thread]) {
        result += item;
    }
    resultArray += result;    // Lock this!
}
waitForThreads();
reduce(resultArray);

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

(Это программное обоснование ответа Петра Лесника .)

Технически уменьшение - это не то же самое, что сложение (влево), которое также можно назвать накоплением.

Пример, приведенный Жюлем, очень хорошо иллюстрирует операцию сокращения:

step 1: 1 + 2 + 3 + 4 
step 2:   3   +   7   
step 3:       10      

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

Сгиб влево выглядит следующим образом:

step 0: a = 0
step 1: a = a + 1 
step 2: a = a + 2 
step 3: a = a + 3
step 4: a = a + 4
step 5: a

Теперь очевидно, что оба они дают одинаковые результаты, но сложение имеет четко определенный результат, если дан неассоциативный оператор (например, вычитание), а оператор сокращения - нет.

Это зависит от вашего шага уменьшения.В реализации MapReduce в стиле Hadoop ваш Редюсер вызывается один раз. за ключ, со всеми строками, соответствующими этому ключу.

Так, например, ваш Mapper может принимать множество неупорядоченных журналов веб-сервера, добавлять некоторые метаданные (например, геокодирование) и выдавать пары [ключ, запись] с идентификатором cookie в качестве ключа.Затем ваш Редюсер будет вызываться один раз для каждого идентификатора файла cookie и получать все данные для этого файла cookie, а также может вычислять совокупную информацию, такую ​​​​как частота посещений или среднее количество страниц, просмотренных за посещение.Или вы можете ввести данные геокодирования и собрать совокупную статистику на основе географического положения.

Даже если вы не выполняете агрегатный анализ по каждому ключу (даже если вы что-то вычисляете по всему набору), возможно, можно разбить ваши вычисления на фрагменты, каждый из которых можно передать в редуктор.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top