Scala: SparkPi 解說

介紹 Spark 的程式架構

Spark 提供以下三種程式寫作方式: Python、 Scala 以及 Java。其中,Scala是其原生支援的程式語言,理論上來說,應該有最簡潔的架構與語法,於是,我們就從 Scala 出發,來看看 SparkPi 是如何撰寫,以下是SparkPi的程式,來自: spark/examples/src/main/scala/org/apache/spark/examples/SparkPi.scala

// scalastyle:off println
package org.apache.spark.examples

import scala.math.random

import org.apache.spark.sql.SparkSession

/** Computes an approximation to pi */
object SparkPi {
  def main(args: Array[String]) {
    val spark = SparkSession
      .builder
      .appName("Spark Pi")
      .config("spark.master", "local")
      .getOrCreate()
    val slices = if (args.length > 0) args(0).toInt else 2
    val n = math.min(100000L * slices, Int.MaxValue).toInt // avoid overflow
    val count = spark.sparkContext.parallelize(1 until n, slices).map { i =>
      val x = random * 2 - 1
      val y = random * 2 - 1
      if (x*x + y*y <= 1) 1 else 0
    }.reduce(_ + _)
    println(s"Pi is roughly ${4.0 * count / (n - 1)}")
    spark.stop()
  }
}
// scalastyle:on println

在程式的一開始,必須先宣告 Spark 的相關設定:

    val spark = SparkSession
      .builder
      .appName("Spark Pi")
      .config("spark.master", "local")
      .getOrCreate()

在所有程式中,去除宣告,變數輸入,溢位保護,輸出之後,只剩下這一部分:

val count = spark.sparkContext.parallelize(1 until n, slices).map { i =>
      val x = random * 2 - 1
      val y = random * 2 - 1
      if (x*x + y*y <= 1) 1 else 0
    }.reduce(_ + _)

以演算法來說,SparkPi 用 Monte Carlo 的方式來計算圓周率,考慮到圓面積為:

πr2\pi r^2

因此,在圓半徑為1時,圓面積為\pi,而 SparkPi 就用 Monte Carlo 的方式來計算半徑為1的圓面積。簡單來說,透過在S個節點平行 (map) 且灑大量在 2X2 區域內撒點 (100000),取得點在圓內的數量 (判斷式回報為1)。

if (x*x + y*y <= 1) 1 else 0

之後,回收個分散節點上的計算 (reduce),換成機率: count / (n - 1),乘上總面積4之後,就得到\pi的數值,n-1 應該是因為degree-of-freedom。 SparkPi 也是一種 MapRedcue 的架構,但是和 hadoop 的 map-reduce 相比,SparkPi 簡單不少,原有的MapReduce 比較像是寫兩隻程式在 hadoop 下偕同運作,而 Scala 下的 SparkPi 則比較像是提出一個工作計畫,然後由 Spark 分配給各節點完成。

Last updated