> For the complete documentation index, see [llms.txt](https://spark-nctu.gitbook.io/spark/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://spark-nctu.gitbook.io/spark/spark-cheng-shi-jie/zuo-sparkpi-jie.md).

# Scala: SparkPi 解說

介紹 Spark 的程式架構

Spark 提供以下三種程式寫作方式: Python、 Scala 以及 Java。其中，Scala是其原生支援的程式語言，理論上來說，應該有最簡潔的架構與語法，於是，我們就從 Scala 出發，來看看 SparkPi 是如何撰寫，以下是SparkPi的程式，來自: [spark/examples/src/main/scala/org/apache/spark/examples/SparkPi.scala](https://github.com/apache/spark/blob/master/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 的方式來計算圓周率，考慮到圓面積為:&#x20;

$$
\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 分配給各節點完成。<br>
