Spark的算法实现
Spark的出现很好的解决了MR程序中间文件落地,造成大量io的问题
在入门学习Spark的时候,接触到了一个求Π的算法
蒙特卡洛算法
作为一个入门级的算法,很好的展示了,多次迭代,得到的结果约等于3.14
–简单理解最后的比值是(圆的占比=4/Π)
通过超级多次的迭代打点,计算出来圆内的点和员外的点的比值,进而反向求出圆周率,因为是随机打点,所以迭代的次数越多,得到的结果就越准确
–在搭建好的集群上,提交我们的样例任务
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://node01:7077,node02:7077,node03:7077 \
--executor-memory 1G \
--total-executor-cores 2 \
/export/servers/spark-2.2.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.2.0.jar \
10000
可以得到这样的结果,看起来应该是迭代的次数越多越接近.可以看到,spark程序将传参10000生成了10000个taks,通过提交命令的2个executor进行调度执行,如果用mr的话,那么10000个task 的 io开销是巨大的,有可能一次迭代的计算过程,都没有一次io那么久
当然本次的主角是–蒙特卡洛算法
但是这次的是调用的spark的样例jar包,没办法直接看到源码,这个时候你可以使用反编译工具,将那个jar进行反编译,也可以搭建spark的源码环境(推荐),
先贴上spark的算法源码
/**
* Computes an approximation to pi
* Usage: JavaSparkPi [partitions]
*/
public final class JavaSparkPi {
public static void main(String[] args) throws Exception {
//创建spark会话
SparkSession spark = SparkSession
//指定本地运行环境
.builder().master("local")
//指定程序名
.appName("JavaSparkPi")
.getOrCreate();
//获取javaSparkContext容器
JavaSparkContext jsc = new JavaSparkContext(spark.sparkContext());
//接收主函数传参--10000 --转换成整数型
int slices = (args.length == 1) ? Integer.parseInt(args[0]) : 2;
//默认将传入的参数扩大10w倍
int n = 100000 * slices;
//进行
List<Integer> l = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
l.add(i);
}
//创建RDD
JavaRDD<Integer> dataSet = jsc.parallelize(l, slices);
int count = dataSet.map(integer -> {
//以圆心作为轴点,取x,y 采用类似勾股定理的原理,
// 判断是(x,y)到圆心的距离是否小于半径来判断是否在圆内
double x = Math.random() * 2 - 1;
double y = Math.random() * 2 - 1;
return (x * x + y * y <= 1) ? 1 : 0;
}).reduce((integer, integer2) -> integer + integer2);
//圆内的比值是Π/4,所以需要在--(圆内的点*4)/总点=Π
System.out.println("Pi is roughly " + 4.0 * count / n);
spark.stop();
}
}
想出这个算法的人真厉害~