![](/img/trans.png)
[英]Why is DataBricks's Spark running slightly faster in Python than Scala
[英]In theory, Scala is faster than Python for Apache Spark. In practice it is not. What's going on?
大家好。 我將盡力解釋我的問題,以便您能理解我。
在幾個地方,我發現它認為Scala比Python快:
此外,據說Scala是最適合在Apache Spark中運行應用程序的編程語言:
https://www.dezyre.com/article/scala-vs-python-for-apache-spark/213
但是,在此站點上,另一個用戶(@Mrityunjay)提出了一個與我在此處提出的問題類似的問題:
在這篇文章中,來自@ zero323的回復突出了以下內容:
通常,回復說明是例外的,使用Scala和Python之間的@ zero323修改可以實現非常相似的執行時間。
考慮到這些信息,我為自己編寫了一個簡單的程序,使我能夠解釋應用程序中發生的類似情況,這突顯了我在Scala中編寫的代碼比在Python中編寫的代碼要慢。 為此,我避免使用ReduceByKey操作,而只使用了map操作。
我將嘗試執行任何超級復雜的操作,以最大程度地提高群集占用率(96核,48 GB RAM)並實現大延遲。 為此,該代碼生成了一組包含標識符ID(長度為10的向量)的一百萬個人工數據(僅出於計算一百萬個數據的處理執行時間(無論是否復制)的目的)。 DoubleS。
由於我的應用程序是使用DataFrame實現的,因此我在Scala中制作了兩個程序,一個使用RDD,另一個使用DataFrame,目的是觀察問題是否出在使用DataFrame。 同樣,用Python編寫了一個等效程序。
通常,將操作應用於每個RDD / DataFrame記錄,並將其結果放置在其他字段中,從而生成一個包含原始字段的新RDD / DataFrame和一個帶有結果的新字段。
這是Scala中的代碼:
import org.apache.spark.sql.SparkSession
import scala.math.BigDecimal
object RDDvsDFMapComparison {
def main(args: Array[String]) {
val spark = SparkSession.builder().appName("Test").getOrCreate()
val sc = spark.sparkContext
import spark.implicits._
val parts = 96
val repl = 1000000
val rep = 60000000
val ary = (0 until 10).toArray
val m = Array.ofDim[Int](repl, ary.length)
for (i <- 0 until repl)
m(i) = ary
val t1_start = System.nanoTime()
if (args(0).toInt == 0) {
val a1 = sc.parallelize(m, parts)
val b1 = a1.zipWithIndex().map(x => (x._2.toString, x._1)).toDF("Name", "Data")
val c1 = b1.map { x =>
val name = x.getString(0)
val data = x.getSeq[Int](1).toArray
var mean = 0.0
for (i <- 0 until rep)
mean += Math.exp(Math.log(data.sum) / Math.log(data.length))
(name, data, mean)
}.toDF("Name", "Data", "Mean")
val d1 = c1.take(5)
println(d1.deep.mkString(","))
} else {
val a1 = sc.parallelize(m, parts)
val b1 = a1.zipWithIndex().map(x => (x._2.toString, x._1))
val c1 = b1.map { x =>
val name = x._1
val data = x._2
var mean = 0.0
for (i <- 0 until rep)
mean += Math.exp(Math.log(data.sum) / Math.log(data.length))
(name, data, mean)
}
val d1 = c1.take(5)
println(d1.deep.mkString(","))
}
val t1_end = System.nanoTime()
val t1 = t1_end - t1_start
println("Map operation elapses: " + BigDecimal(t1.toDouble / 1000000000).setScale(2, BigDecimal.RoundingMode.HALF_UP).toDouble.toString + " seconds.")
}
}
這是Python中的代碼(簡單得多):
#!/usr/bin/python
# -*- coding: latin-1 -*-
import sys
import time
import math
from pyspark import SparkContext, SparkConf
def myop(key, value):
s = 0.0
for j in range(r):
s += math.exp(math.log(sum(value)) / math.log(float(len(value))))
return (key, value, s)
if __name__ == "__main__":
conf = SparkConf().setAppName("rddvsdfmapcomparison")
sc = SparkContext(conf=conf)
parts = 96
repl = 1000000
r = 60000000
ary = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
m = []
for i in range(repl): m.append(ary)
start = time.time()
a2 = sc.parallelize(m, parts)
b2 = a2.zipWithIndex().map(lambda (value, key): (key, value))
c2 = b2.map(lambda (key, value): myop(key, value))
c2.count
d2 = c2.take(5)
print '[%s]' % ', '.join(map(str, d2))
end = time.time()
print 'Elapsed time is', round(end - start, 2), 'seconds'
sc.stop()
結果非常清楚。 使用RDD或DataFrame,用Python實現的程序比用Scala實現的程序要快。 還可以觀察到,RDD中的程序比DataFrame中的程序稍快,這是一致的,這是由於使用了解碼器提取了DataFrame記錄的每個字段的數據類型。
問題是,我在做什么錯? Scala代碼難道不比Python快嗎? 有人可以向我解釋我的代碼在做什么錯嗎? @ zero323的響應非常好,很說明問題,但是我不明白在Scala中像這樣的簡單代碼比Python中的慢。
非常感謝您抽出寶貴時間閱讀我的問題。
在Scala中嘗試此實現。 它更快:
import org.apache.spark.sql.functions.udf
import org.apache.spark.sql.functions._
val spark = SparkSession.builder().appName("Test").getOrCreate()
val sc = spark.sparkContext
import spark.implicits._
val parts = 96
val repl = 1000000
val rep = 20000
val m = Vector.tabulate(repl, 10)((_,i) => i)
val myop = udf( (value: Seq[Int]) =>
(0 until rep).foldLeft(0.0) {(acc,_)=>
acc + Math.exp(Math.log(value.sum) / Math.log(value.length))
}
)
val c1 = sc.parallelize(m, parts)
.toDF("Data")
.withColumn("Name",monotonically_increasing_id())
.withColumn("Mean",myop('Data))
c1.count()
val d1 = c1.take(5)
println(d1.deep.mkString(","))
我想如果我了解myop
實際正在執行的功能,它甚至可能會更干凈。
編輯:
正如@ user6910411在評論中提到的那樣,此實現速度更快是因為它的執行與Python的代碼完全相同(跳過了大部分計算)。 問題中提供的原始Scala和Python實現不相等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.