迭代地图并减少操作

时间:2012-11-18 14:20:58

标签: map hadoop mapreduce loops reduce

我正在编写一个Hadoop应用程序以一定的分辨率计算地图数据。我的输入文件是地图的图块,根据QuadTile原则命名。我需要对它们进行子采样,并将它们拼接在一起,直到我有一个更高级别的区块,覆盖更大的区域,但分辨率更低。就像在谷歌地图中缩小一样。

目前我的Mapper子样本瓷砖和我的减速器将瓷砖组合在一定水平并形成一层的瓷砖。所以这么好。但是根据我需要的哪个图块,我需要重复这些图并将步骤减少x次,这是迄今为止我无法做到的。

最好的方法是什么?是否可以在没有明确地将tile保存在某个临时目录中并在那些临时目录上启动新的mapreduce作业,直到我得到我想要的为止?我认为完美的解决方案大致类似于'while(context.hasMoreThanOneKey()){iterate mapreduce}'。

在回答之后,我现在写了一个TileJob类来扩展Job。但是,mapreduc仍然没有链接。你能告诉我我做错了吗?

public boolean waitForCompletion(boolean verbose) throws IOException, InterruptedException, ClassNotFoundException{

    if(desiredkeylength != currentinputkeylength-1){            
        System.out.println("In loop, setting input at " + tempout);
        String tempin = tempout;
        FileInputFormat.setInputPaths(this, tempin);            
        tempout = (output + currentinputkeylength + "/");
        FileOutputFormat.setOutputPath(this, new Path(tempout));
        System.out.println("Setting output at " + tempout);
        currentinputkeylength--;
        Configuration conf = new Configuration();
        TileJob job = new TileJob(conf);
        job.setJobName(getJobName());
        job.setUpJob(tempin, tempout, tiletogenerate, currentinputkeylength);       
         return job.waitForCompletion(verbose);

    }else{
        //desiredkeylength == currentkeylength-1
        System.out.println("In else, setting input at " + tempout);

        String tempin = tempout;
        FileInputFormat.setInputPaths(this, tempin);            
        tempout = output;
        FileOutputFormat.setOutputPath(this, new Path(tempout));
        System.out.println("Setting output at " + tempout);
        currentinputkeylength--;
        Configuration conf = new Configuration();
        TileJob job = new TileJob(conf);
        job.setJobName(getJobName());
        job.setUpJob(tempin, tempout, tiletogenerate, currentinputkeylength);
        currentinputkeylength--;

        return super.waitForCompletion(verbose);
    }   

}

1 个答案:

答案 0 :(得分:1)

通常通过使用配置作业,配置和格式类型(输入和输出)的驱动程序类main方法来启动mapreduce步骤。一切准备就绪后,主方法调用Job :: waitForCompletion()提交作业并等待作业完成后再继续。

您可以将一些逻辑包装在一个循环中,该循环重复调用Job :: waitForCompletion()直到满足您的条件。您可以使用计数器实施标准。将逻辑放入reduce()方法,以设置或增加具有键数的计数器。您在驱动程序类中的循环可以从Job实例获取该(分布式)计数器的值,并使用该值对while表达式进行编码。

您使用的文件位置取决于您。在此驱动程序循环中,您可以更改输入和输出的文件位置,或保持它们相同。

我应该补充一点,你应该继续在循环中创建一个新的Job和Configuration实例。我不知道在这种情况下这些对象是可重用的。

public static void main(String[] args) {
    int keys = 2;
    boolean completed = true;
    while (completed & (keys > 1)) {

        Job job = new Job();

            // Do all your job configuration here

        completed = job.waitForCompletion();
        if (completed) {
            keys = job.getCounter().findCounter("Total","Keys").getValue();
        }
    }

}