如果使用MapReduce执行的操作不是交换式和结合式的,则合并器不能与减法器相同。
例如,在计算平均值时,组合器对键的值求和,减法器对其求和,然后将和除以该键的值的总数。合并器的代码只有很小的修改。如果您可以对组合器和reducer使用相同的类,并且可以轻松地确定当前任务是组合器还是reducer,会发生什么呢?如果它发现它是一个减法器,那么它就将和除以计数。
如下所示:
protected void reduce(Text keyIn, Iterable<PairWritable> valuesIn,
Context context)
throws IOException, InterruptedException {
double sum = 0.0d;
long count = 0l;
for (PairWritable valueIn : valuesIn) {
sum += valueIn.getSum();
count += valueIn.getCount();
}
if (THIS_IS_A_REDUCER) {
sum /= count;
}
context.write(keyIn, new PairWritable(sum, count));
}
有可能做到这一点吗?上面的代码THIS_IS_A_REDUCER
可以被替换成其他东西吗?
我可以根据任务尝试ID字符串确定任务是映射器还是减法器,但组合器和减法器似乎都有类似的字符串模式。
发布于 2012-08-13 13:25:38
我想您可以询问Context
对象并获得任务ID,然后,一旦您有了ID,映射器(包括组合器)的名称中将有一个"m“,而reducer的名称中将有一个"r”。
要获取任务尝试ID,请使用.getTaskAttemptID()。我认为你应该能够使用context.getTaskAttemptID()
来使用它,但是我不能测试它来确定。
发布于 2012-10-23 23:21:32
这是一个有缺陷的问题。无论何时您发现需要区分任务调用了哪个reduce()。添加一个组合器。例如,您可以这样写
public static class Combine extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}
public static class Reduce extends MapReduceBase implements Reducer<Text, Text, Text, Text> {
public void reduce(Text key, Iterator<Text> message, OutputCollector<Text, Text> output, Reporter reporter) throws IOException {}
在main()中,您可以这样写
conf.setReducerClass(Reduce.class);
conf.setCombinerClass(Combine.class);
发布于 2013-04-10 21:03:53
虽然我知道这个问题已经解决了,但我有另一个解决方案。我所做的就是让我的Combiner成为Reducer的子类。然后,在Reducer代码中,我可以测试我是否是Combiner子类。
这样做的主要好处是我需要在Reducer步骤中修改我的键,但不想在合并步骤中更改它(否则我会应用相同的转换两次)。除此之外,95%的代码是相同的。
https://stackoverflow.com/questions/11928316
复制相似问题