在用Java编写的Hadoop MapReduce作业中 在REDUCE的阶段,我发现分裂的不稳定性。在具有X double的特定1 / X中:
double sum = 0;
while (values.hasNext())
{
sum += values.next().get();
}
if (sum != 0) {
output.collect(key, new DoubleWritable(1/sum));
} else {
output.collect(key, new DoubleWritable(1));
}
值是迭代器。
当总和与ZERO不同时,有时会写1 / sum和SOMETIMES WRITE sum。 它让我发疯。 非常感谢
[解决] 我有另一个问题,MAPPER和REDUCER接口(键值)不同。 (Text,InteWritable)第一个(Text,DoubleWritable)第二个。 我在“主要”中配置了这些东西。错误仍在继续,因为我把这一行放错了:
conf.setCombinerClass(Reduce.class);
在mapper和reducer中需要相同的接口(k,v),这不是我的情况; 删除一切正常。 感谢Arnon Rotem-Gal-Oz,我没有声誉支持他
答案 0 :(得分:1)
你的问题是,在计算总和时,浮点值的加法是不可交换的(其原因是double的有限精度)。用简单的话来说:总和受到元素添加顺序的影响。
这段代码很好地证明了这一点:
public class DoubleSumDemo {
public static void main(String[] argv) {
final ArrayList<Double> list = new ArrayList<Double>();
// fill list with random values
for (int i=0; i<1000000; ++i)
list.add(Math.random());
// sum the list, print the sum and then reorder the list elements
while (true) {
double sum = 0D;
for (double element : list)
sum += element;
System.out.println("sum is: " + sum);
Collections.shuffle(list);
}
}
}
虽然列表只填充一次,但它会在每个循环上打印不同的总和。