Hadoop mapreduce с размером ввода ~ 2Mb медленно

Я попытался распространить расчет, используя hadoop.

Я использую входные и выходные файлы последовательности и пользовательские записываемые файлы.

Входные данные представляют собой список треугольников, максимальный размер которых составляет 2 МБ, но они также могут быть меньше примерно на 50 КБ. Промежуточными значениями и выводом является карта (int,double) в настраиваемой форме записи. Это узкое место?

Проблема в том, что расчет намного медленнее, чем версия без hadoop. Кроме того, увеличение узлов с 2 до 10 не ускоряет процесс.

Одна возможность состоит в том, что я не получаю достаточно картографов из-за небольшого размера ввода. Я сделал тесты, изменяя mapreduce.input.fileinputformat.split.maxsize, но стало только хуже, а не лучше.

Я использую hadoop 2.2.0 локально, и в amazon упругое отображение.

Я что-то упустил? Или это именно та задача, которую следует выполнять без Hadoop? (это мой первый раз, используя mapreduce).

Хотите увидеть части кода?

Спасибо.

public void map(IntWritable triangleIndex, TriangleWritable triangle, Context context) throws IOException, InterruptedException {           
        StationWritable[] stations = kernel.newton(triangle.getPoints());
        if (stations != null) {
            for (StationWritable station : stations) {
                context.write(new IntWritable(station.getId()), station);
            }
        }
    }    


class TriangleWritable implements Writable {

private final float[] points = new float[9];

@Override
public void write(DataOutput d) throws IOException {
    for (int i = 0; i < 9; i++) {
        d.writeFloat(points[i]);
    }
}

@Override
public void readFields(DataInput di) throws IOException {
    for (int i = 0; i < 9; i++) {
        points[i] = di.readFloat();
    }
}
}

public class StationWritable implements Writable {

private int id;
private final TIntDoubleHashMap values = new TIntDoubleHashMap();

StationWritable(int iz) {
    this.id = iz;
}

@Override
public void write(DataOutput d) throws IOException {
    d.writeInt(id);
    d.writeInt(values.size());
    TIntDoubleIterator iterator = values.iterator();
    while (iterator.hasNext()) {
        iterator.advance();
        d.writeInt(iterator.key());
        d.writeDouble(iterator.value());
    }
}

@Override
public void readFields(DataInput di) throws IOException {
    id = di.readInt();

    int count = di.readInt();
    for (int i = 0; i < count; i++) {
        values.put(di.readInt(), di.readDouble());
    }
}
}

3 ответа

Решение

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

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

Таким образом, вы сможете получить преимущества, которые вы ищете от Hadoop Map Reduce, но, вероятно, потребуется значительная настройка и пользовательская обработка ввода.

При этом редко (никогда?) MapReduce будет быстрее, чем специально разработанное решение. Это универсальный инструмент, который полезен тем, что его можно использовать для распространения и решения многих разнообразных проблем без необходимости написания специального решения для каждой из них.

Вы не получите никакой выгоды от hadoop только с 2 МБ данных. Hadoop - это все о больших данных. Распределение 2 МБ на ваши 10 узлов требует больше времени, чем просто выполнение работы на одном узле. Настоящая выгода начинается с большого количества узлов и огромных данных.

Итак, в конце я нашел способ не хранить промежуточные значения в доступных для записи, только в памяти. Так быстрее. Но, тем не менее, решение non-hadoop является лучшим в этом случае.

Другие вопросы по тегам