Hadoop: Возможно ли иметь в памяти структуры в функции карты и объединять их? - PullRequest
1 голос
/ 01 марта 2012

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

Это статья, на которую я ссылаюсь: http://research.google.com/pubs/pub36296.html

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

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

Это то, что они говорят в этой газете

При запуске каждый картограф загружает набор точек разделения учитывается для каждого упорядоченного атрибута. Для каждого узла n ∈ N и атрибут X, преобразователь поддерживает таблицу Tn, X пары значений.

После обработки всех входных данных картографы положить ключи вида n, X и значения v, Tn, X [v]

Вот некоторые правки после ответа Шона:

Я использую комбайнер в своей работе. Дело в том, что эти команды context.write (Text, Text) в моей функции карты действительно отнимают много времени. Мой ввод - CSV-файлы или ARFF-файлы. В каждой строке есть пример. Мои примеры могут иметь до тысячи атрибутов. Я вывожу для каждого атрибута пары ключ-значение в виде <(n, X, u), Y>, где - имя узла (я строю дерево решений), X - имя атрибута, u - значение атрибута, а Y - некоторая статистика в текстовом формате. Как вы можете сказать, если у меня есть 100 000 атрибутов, у меня будет 100 000 команд context.write (Text, Text) для каждого примера. Запустив мою задачу карты без этих команд, она работает как ветер. Если я добавлю команду context.write, это займет вечность. Даже за 2000 тысяч атрибутов учебного комплекта. Похоже, я пишу в файлах, а не в памяти. Так что мне действительно нужно уменьшить эти записи. Необходимо объединить их в памяти (в функции карты, а не в объединителе).

Ответы [ 2 ]

1 голос
/ 01 марта 2012

Добавление другого ответа, так как теперь я вижу смысл вопроса.

Чтобы знать, когда задача карты заканчивается, вы можете переопределить close().Я не знаю, если это то, что вы хотите.Если у вас 50 картографов, 1/50 входных данных, которые каждый видит, неизвестна или не гарантирована.Это нормально для вашего варианта использования - вам просто нужно, чтобы каждый работник агрегировал статистику в памяти для того, что он видел и выводил?

Тогда ваша процедура в порядке, но, вероятно, не сделает вашу структуру данных в памяти static - никто не говорил, что два Mapper не будут работать в одном загрузчике классов JVM.

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

Я не уверен, что это работает, поскольку узкое место возникает до Reducer.

1 голос
/ 01 марта 2012

Не зная немного больше о деталях того, что вы выводите, я не могу быть уверен, поможет ли это, но это звучит как то, для чего предназначен комбинатор. Это похоже на миниатюрный редуктор (на самом деле реализация объединителя - это просто еще одна реализация Reducer), присоединенная к выходу Mapper. Его цель - собрать выходные записи карты в памяти и попытаться объединить их перед записью на диск, а затем собрать с помощью Reducer.

Классический пример - подсчет значений. Вы можете вывести «key, 1» из вашей карты, а затем добавить 1 в редуктор, но это включает в себя вывод «key, 1» 1000 раз из преобразователя, если ключ появляется 1000 раз, когда «key, 1000» будет достаточно , Объединитель делает это. Конечно, это применимо только тогда, когда рассматриваемая операция является ассоциативной / коммутативной и может выполняться многократно без побочных эффектов - хорошим примером является сложение.

Другой ответ: в Mahout мы реализуем много вещей, которые являются одновременно странными, немного сложными и очень медленными, если сделать это простым способом. Использование трюков, таких как сбор данных в памяти в Mapper, является второстепенным и иногда необходимым грехом, так что в этом нет ничего страшного. Это означает, что вам действительно нужно знать семантику, которую гарантирует Hadoop, хорошо тестировать и думать о нехватке памяти, если не будете осторожны.

...