一、hadoop不适合计算密集型的工作
以前看过一个PPT: Hadoop In 45 Minutes or Less ,记得上面说hadoop不适合计算密集型的工作,比如计算PI后100000位小数。
但是,前几天,我却发现了在hadoop自带的examples里,竟然有PiEstimator这个例子!!它是怎么做到的??
三、一定要用hadoop吗?
在《通过扔飞镖也能得出PI的值?》一文中,网页中自带了一个Flash,用ActionScript来计算PI的值。
用这种算法来估算PI值,其实是一个统计学的方法。如果要估算正确,首先要保证取样足够多(即投掷次数足够多)。但是如果是单机上运行程序,取太多的样,很容易crash your computer.
所以,这里用hadoop的原因可以在集群上并行运行多个map任务,同时集群上的节点又非常多,这样就能够保证取到足够多的样了!
四、hadoop examples代码解读
上代码:
public void map(LongWritable offset,
LongWritable size,
OutputCollector<BooleanWritable, LongWritable> out,
Reporter reporter) throws IOException {
final HaltonSequence haltonsequence = new HaltonSequence(offset.get());
long numInside = 0L;
long numOutside = 0L;
for(long i = 0; i < size.get(); ) {
//generate points in a unit square
final double[] point = haltonsequence.nextPoint();
// 1、point就是取样点,即飞镖投中的部位。这是一个x和y都是0到1的值(Halton sequence保证这一点)。此时的坐标原点在A(见Figure1)。
//count points inside/outside of the inscribed circle of the square
final double x = point[0] - 0.5;
final double y = point[1] - 0.5;
// 2、横纵坐标各减去0.5以后,我们就可以理解成:将坐标原点从A移到了B(见Figure1)。
if (x*x + y*y > 0.25) { // 3、根据勾股定理:x*x+y*y > 0.5*0.5(见Figure2),判断这个point是否在圆里。
numOutside++;
} else {
numInside++;
}
//report status
i++;
if (i % 1000 == 0) {
reporter.setStatus("Generated " + i + " samples.");
}
}
//output map results
out.collect(new BooleanWritable(true), new LongWritable(numInside));
out.collect(new BooleanWritable(false), new LongWritable(numOutside));
}
还需要说明的是:
1、mapper的输出:
//output map results
out.collect(new BooleanWritable(true), new LongWritable(numInside));// 投中的次数
out.collect(new BooleanWritable(false), new LongWritable(numOutside));
2、reducer,简单的对numInside进行sum操作。
3、最后,PI的值等于:
//compute estimated value
return BigDecimal.valueOf(4) // 上面图中公式中的4
.setScale(20)//精度
.multiply(BigDecimal.valueOf(numInside.get()))// 投中的次数
.divide(BigDecimal.valueOf(numMaps))// mapper的数量
.divide(BigDecimal.valueOf(numPoints));// 每个mapper投掷多少次
总共投掷的次数 = mapper的数目*每个mapper投掷的次数
PI = 4 * 投中的次数 / 总共投掷的次数
附:运行hadoop估算PI的命令
hadoop jar $HADOOP_HOME/hadoop-*-examples.jar pi 100 100000000
后面2个数字参数的含义:
第1个100指的是要运行100次map任务
第2个数字指的是每个map任务,要投掷多少次
2个参数的乘积就是总的投掷次数。
我运行的结果:
Job Finished in 7492.442 seconds
Estimated value of Pi is 3.14159266720000000000