Beam 超實用examples之Pi值計算

Beam Pi值計算





0?wx_fmt=jpeg

Beam剛剛開源不是很久,快2個月了。目前的版本是0.5.0版本。官方的源碼中提供了4個examples.無奈這四個案例都只是WordCount的四種不同的實現。作爲一個從Spark進入大數據殿堂的筆者來說,用過n多次的SparkPi的我,怎麼能忍受竟然沒有Pi實現的example呢。假如有了這個案例,可以非常方便的無論在開發工具中還是在集羣中進行測試。於是便有了下文。筆者的文筆和技術有限。不足之處,還望朋友多多提建議。Let us come on 。

我們先來講講Pi的實現原理。我們是用概率統計的方法來實現的。先來想象一下,以一個單位爲半徑畫圓,再畫一個圓的外切正方形。假設一個杯子的底部就被這個正方形和正方形內切圓全部填滿。做n次試驗,往杯子中扔石頭,落在圓內的次數除以總次數是不是Pi*r*r/2r*2r也就是Pi/4.

因此,Pi就是4倍的此概率。


以下是代碼的試驗。僅供參考。

0?wx_fmt=png

0?wx_fmt=png

0?wx_fmt=png

0?wx_fmt=png

0


可以複製代碼

package org.tongfang.beam.examples;


import java.util.ArrayList;

import java.util.List;



import org.apache.beam.runners.spark.SparkRunner;

import org.apache.beam.sdk.Pipeline;

import org.apache.beam.sdk.options.PipelineOptions;

import org.apache.beam.sdk.options.PipelineOptionsFactory;

import org.apache.beam.sdk.transforms.*;


public class BeamPi {


public static void main(String[] args) {

// Beam Pi的自定義實現方式

//第一步驟:創建options,

//通過該對象可以選擇使用哪個計算框架來計算,並且設置應用的名稱

PipelineOptions options = PipelineOptionsFactory.create();

//設置job(應用)名稱

options.setJobName("Beam Pi");

//設置runner爲Spark

options.setRunner(SparkRunner.class);

//創建管道 p

Pipeline p = Pipeline.create(options);

//100000000次的隨機試驗的次數,如果資源,

//足夠的大可以進行更多次的試驗,用大數據的理論來說,

//理論上可以進行無數次的試驗(只要不斷的橫向擴展計算的資源)。

List<Integer> list = new ArrayList<Integer>();

for(int i = 0;i<1000000;i++){

list.add(i);

}


//相當於Spark從內存中讀取數據,並通過map迭代訪問每一個元素,

//這裏迭代1000000的訪問每個依次增大的數字,

//沒迭代一次,做一次試驗,當點落到圓內,計數增加1,否則不計數

//也就是什麼也不做

//然後再近些Count計數,最後計數結果除以試驗次數,就是概率。

//從數學角度來看,PI的值就是4倍這個概率。從而計算出PI的值。

p.apply(Create.of(list)).apply(ParDo.of(new DoFn<Integer, Integer>() {

double x = 0;

double y = 0;

private static final long serialVersionUID = 1L;

 @ProcessElement

         public void processElement(ProcessContext c) {

           x = Math.random() * 2 - 1;;

y = Math.random() * 2 - 1;;

if((x*x+y*y)<1){

c.output(1);

}else{

}

          

 }

})).apply( Count.<Integer>globally()).

apply(MapElements.via(new SimpleFunction<Long, Void>() {


/**

 * 

 */

private static final long serialVersionUID = 1L;


public Void apply(Long input) {

Float res = (float) (4.0*(float)input / 1000000f);

System.out.println(input);

System.out.println("PI :  "+res);


return null;

}

}));

//這是運行計算的關鍵,如果這個代碼不寫,

//整個代碼都是懶加載,並非真正計算。

p.run().waitUntilFinish();

}


}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章