Я пишу приложение Hadoop, но кажется, что я неправильно истолковал, как именно работает Hadoop. Мои входные файлы представляют собой фрагменты карты, названные в соответствии с принципом QuadTile. Мне нужно выполнить подвыборку и сшить их вместе, пока у меня не будет определенной плитки более высокого уровня, которая покрывает большую площадь, но с более низким разрешением. Например, уменьшение масштаба в картах Google.
Одна из вещей, которые я сделал, это то, что я написал маппер, который выполняется на каждом (неразделяемом) тайле следующим образом:
public void map(Text keyT, ImageWritable value, Context context) throws IOException, InterruptedException {
String key = keyT.toString();
//check whether file needs to be processed
if(key.startsWith(context.getJobName(), 0)){
String newKey = key.substring(0, key.length()-1);
ImageWritable iw = subSample(value);
char region = key.charAt(key.length()-1);
iw.setRegion(region);
context.write(new Text(newKey), iw);
}else{
//tile not needed in calculation
}
}
Мой редуктор выглядит так:
public void reduce(Text key, Iterable<ImageWritable> values, Context context) throws IOException, InterruptedException{
ImageWritable higherLevelTile = new ImageWritable();
int i = 0;
for(ImageWritable s : values){
int width = s.getWidth();
int height = s.getHeight();
char c = Character.toUpperCase(s.getRegion());
int basex=0, basey=0;
if(c=='A'){
basex = basey = 0;
}else if(c=='B'){
basex = width;
basey = 0;
}else if(c=='C'){
basex = 0;
basey = height;
}else{
basex = width;
basey = height;
}
BufferedImage toDraw = s.getBufferedImage();
Graphics g = higherLevelTile.getBufferedImage().getGraphics();
g.drawImage(toDraw, basex, basey, null);
}
context.write(key, higherLevelTile);
}
Как вы, возможно, можете извлечь из моего кода, я ожидал, что hadoop будет выполняться следующим образом: 1) Сопоставьте все плитки первого уровня 2) Выполните первое сокращение. здесь я ожидал, что значения Iterable будут иметь четыре элемента: четыре субдискретизированных плитки нижнего уровня. 3) Отобразить все плитки в настоящее время в контексте 4) уменьшить все плитки в контексте. Опять же, значения Iterable будут иметь 4 элемента... 5) ... повторить... 6) когда больше не останется карт -> запись вывода
Оказывается, это не правильно. Мой редьюсер вызывается после каждой карты, и у Iterable никогда не бывает более одного элемента. Я попытался исправить это, немного изменив код редуктора, предполагая, что Iterable будет иметь 2 элемента: одно субдискретизированное значение и один частично законченный тайл более высокого уровня. Оказывается, это тоже не правильно.
Может ли кто-нибудь сказать мне или указать мне, как на самом деле работает поток хаупов? Что я должен сделать, чтобы мой вариант использования работал? Надеюсь понятно объяснил.