ประสิทธิภาพการจุดประกายสำหรับ Scala vs Python


178

ฉันชอบ Python มากกว่า Scala แต่เนื่องจาก Spark เขียนขึ้นโดยกำเนิดในภาษา Scala ฉันคาดว่ารหัสของฉันจะทำงานได้เร็วขึ้นใน Scala มากกว่ารุ่น Python ด้วยเหตุผลที่ชัดเจน

ด้วยสมมติฐานดังกล่าวฉันคิดว่าเรียนรู้และเขียนรุ่น Scala ของโค้ด preprocessing ที่ใช้กันทั่วไปสำหรับข้อมูล 1 GB บางส่วน ข้อมูลจะถูกหยิบมาจากการแข่งขันใน Springleaf Kaggle เพียงเพื่อให้ภาพรวมของข้อมูล (มันมีขนาด 1,936 และ 145232 แถว) ข้อมูลประกอบด้วยประเภทต่างๆเช่น int, float, string, boolean ฉันใช้ 6 คอร์จาก 8 สำหรับการประมวลผล Spark; นั่นเป็นเหตุผลที่ฉันใช้minPartitions=6เพื่อให้ทุกแกนมีบางอย่างที่ต้องดำเนินการ

รหัสสกาล่า

val input = sc.textFile("train.csv", minPartitions=6)

val input2 = input.mapPartitionsWithIndex { (idx, iter) => 
  if (idx == 0) iter.drop(1) else iter }
val delim1 = "\001"

def separateCols(line: String): Array[String] = {
  val line2 = line.replaceAll("true", "1")
  val line3 = line2.replaceAll("false", "0")
  val vals: Array[String] = line3.split(",")

  for((x,i) <- vals.view.zipWithIndex) {
    vals(i) = "VAR_%04d".format(i) + delim1 + x
  }
  vals
}

val input3 = input2.flatMap(separateCols)

def toKeyVal(line: String): (String, String) = {
  val vals = line.split(delim1)
  (vals(0), vals(1))
}

val input4 = input3.map(toKeyVal)

def valsConcat(val1: String, val2: String): String = {
  val1 + "," + val2
}

val input5 = input4.reduceByKey(valsConcat)

input5.saveAsTextFile("output")

รหัสหลาม

input = sc.textFile('train.csv', minPartitions=6)
DELIM_1 = '\001'


def drop_first_line(index, itr):
  if index == 0:
    return iter(list(itr)[1:])
  else:
    return itr

input2 = input.mapPartitionsWithIndex(drop_first_line)

def separate_cols(line):
  line = line.replace('true', '1').replace('false', '0')
  vals = line.split(',')
  vals2 = ['VAR_%04d%s%s' %(e, DELIM_1, val.strip('\"'))
           for e, val in enumerate(vals)]
  return vals2


input3 = input2.flatMap(separate_cols)

def to_key_val(kv):
  key, val = kv.split(DELIM_1)
  return (key, val)
input4 = input3.map(to_key_val)

def vals_concat(v1, v2):
  return v1 + ',' + v2

input5 = input4.reduceByKey(vals_concat)
input5.saveAsTextFile('output')

การแสดงสกาล่า ระยะที่ 0 (38 นาที), ระยะที่ 1 (18 วินาที) ป้อนคำอธิบายรูปภาพที่นี่

Python Performance ระยะ 0 (11 นาที), ระยะ 1 (7 วินาที) ป้อนคำอธิบายรูปภาพที่นี่

ทั้งคู่สร้างกราฟการสร้างภาพ DAG ที่แตกต่างกัน (เนื่องจากรูปภาพทั้งสองแสดงฟังก์ชันระยะ 0 ที่แตกต่างกันสำหรับ Scala ( map) และ Python ( reduceByKey)

แต่โดยพื้นฐานแล้วโค้ดทั้งสองพยายามแปลงข้อมูลให้เป็น (dimension_id สตริงของรายการค่า) RDD และบันทึกลงดิสก์ เอาต์พุตจะถูกใช้เพื่อคำนวณสถิติต่างๆสำหรับแต่ละมิติ

ประสิทธิภาพที่ชาญฉลาดโค้ดสกาล่าสำหรับข้อมูลจริงเช่นนี้ดูเหมือนว่าจะทำงานช้ากว่ารุ่น Python ถึง4 เท่า ข่าวดีสำหรับฉันก็คือมันทำให้ฉันมีแรงจูงใจที่ดีที่จะอยู่กับงู ข่าวร้ายคือฉันไม่เข้าใจว่าทำไม


8
บางทีนี่อาจเป็นโค้ดและแอปพลิเคชันที่ต้องพึ่งพาเมื่อฉันได้ผลลัพธ์อีกอย่างหนึ่งนั่นคือapache spark python ช้ากว่า scala เมื่อรวมสูตร Leibniz หลายพันคำสำหรับπ
Paul

3
คำถามที่น่าสนใจ! Btw, ดูที่นี่ด้วย: emptypipes.org/2015/01/17/python-vs-scala-vs-sparkยิ่งคุณมีแกนมากเท่าไหร่คุณก็จะยิ่งเห็นความแตกต่างระหว่างภาษาน้อยลงเท่านั้น
Markon

คุณคิดว่าจะยอมรับคำตอบที่มีอยู่ไหม?
10465355 พูดว่า Reinstate Monica

คำตอบ:


358

คำตอบดั้งเดิมเกี่ยวกับรหัสสามารถพบได้ที่ด้านล่าง


ก่อนอื่นคุณต้องแยกแยะความแตกต่างของ API แต่ละประเภทด้วยการพิจารณาประสิทธิภาพของตัวเอง

API RDD

(โครงสร้าง Python ล้วนๆพร้อมการประสานแบบ JVM)

นี่คือองค์ประกอบที่จะได้รับผลกระทบมากที่สุดจากประสิทธิภาพของรหัส Python และรายละเอียดของการใช้งาน PySpark ในขณะที่ประสิทธิภาพของ Python นั้นไม่น่าเป็นปัญหา แต่อย่างน้อยก็มีปัจจัยบางอย่างที่คุณต้องพิจารณา:

  • โอเวอร์เฮดของการสื่อสาร JVM ข้อมูลทั้งหมดที่มาถึงและจากผู้ดำเนินการหลามจวนจะต้องถูกส่งผ่านซ็อกเก็ตและผู้ปฏิบัติงาน JVM แม้ว่านี่จะเป็นการสื่อสารในท้องถิ่นที่มีประสิทธิภาพ แต่ก็ยังไม่ฟรี
  • ตัวประมวลผลแบบอิงกระบวนการ (Python) และตัวประมวลผล (Scala) แบบเธรด (เธรดเดี่ยว JVM หลายเธรด) ตัวจัดการ Python แต่ละตัวทำงานในกระบวนการของตัวเอง ในฐานะที่เป็นผลข้างเคียงมันให้การแยกที่แข็งแกร่งกว่า JVM คู่กันและการควบคุมวงจรชีวิตของตัวจัดการบางอย่าง แต่อาจมีการใช้หน่วยความจำที่สูงขึ้นอย่างมีนัยสำคัญ:

    • ล่ามรอยหน่วยความจำ
    • รอยเท้าของห้องสมุดที่โหลด
    • การออกอากาศที่มีประสิทธิภาพน้อยกว่า (แต่ละกระบวนการต้องการสำเนาการออกอากาศ)
  • ประสิทธิภาพของรหัสหลามเอง โดยทั่วไปการพูด Scala เร็วกว่า Python แต่มันจะแตกต่างกันไปในแต่ละงาน นอกจากนี้คุณมีตัวเลือกหลายอย่างรวมทั้ง JITs เช่นNumbaส่วนขยาย C ( Cython ) หรือห้องสมุดเฉพาะเช่นTheano สุดท้ายถ้าคุณไม่ใช้ ML / MLlib (หรือเพียงแค่ NumPy stack)ให้ลองใช้PyPyเป็นล่ามทางเลือก ดูSPARK-3094

  • การกำหนดค่า PySpark มีspark.python.worker.reuseตัวเลือกที่สามารถใช้ในการเลือกระหว่างการดำเนินการ Python สำหรับแต่ละงานและนำกระบวนการที่มีอยู่กลับมาใช้ใหม่ ตัวเลือกหลังดูเหมือนว่าจะมีประโยชน์ในการหลีกเลี่ยงการเก็บขยะที่มีราคาแพง (มันเป็นความประทับใจมากกว่าผลของการทดสอบอย่างเป็นระบบ) ในขณะที่ตัวเลือกก่อนหน้า (ค่าเริ่มต้น) นั้นดีที่สุดสำหรับกรณีที่การออกอากาศและการนำเข้ามีราคาแพง
  • การนับการอ้างอิงใช้เป็นวิธีการรวบรวมขยะบรรทัดแรกใน CPython ทำงานได้ดีกับปริมาณงาน Spark ทั่วไป (การประมวลผลคล้ายกระแสไม่มีรอบอ้างอิง) และลดความเสี่ยงของ GC หยุดชั่วคราว

MLlib

(การดำเนินการ Python และ JVM แบบผสม)

ข้อควรพิจารณาขั้นพื้นฐานคล้ายกับปัญหาเพิ่มเติมเล็กน้อยก่อนหน้านี้ ในขณะที่โครงสร้างพื้นฐานที่ใช้กับ MLlib เป็นวัตถุ Python RDD ธรรมดาขั้นตอนวิธีทั้งหมดจะถูกดำเนินการโดยตรงโดยใช้ Scala

มันหมายถึงค่าใช้จ่ายเพิ่มเติมในการแปลงออบเจ็กต์ Python ให้เป็นออบเจกต์ Scala และอีกวิธีหนึ่งการเพิ่มการใช้หน่วยความจำและข้อ จำกัด เพิ่มเติมบางอย่างที่เราจะกล่าวถึงในภายหลัง

ณ ตอนนี้ (Spark 2.x) API ของ RDD-based อยู่ในโหมดการบำรุงรักษาและมีกำหนดจะถูกลบออกใน Spark 3.0

DataFrame API และ Spark ML

(การดำเนินการ JVM ด้วยรหัส Python จำกัด เฉพาะไดรเวอร์)

สิ่งเหล่านี้อาจเป็นตัวเลือกที่ดีที่สุดสำหรับงานการประมวลผลข้อมูลมาตรฐาน เนื่องจากรหัส Python ส่วนใหญ่ถูก จำกัด ไว้ที่การดำเนินการทางตรรกะระดับสูงในไดรเวอร์จึงไม่ควรมีประสิทธิภาพที่แตกต่างระหว่าง Python และ Scala

ข้อยกเว้นเดียวคือการใช้ Python UDFs แบบชาญฉลาดซึ่งมีประสิทธิภาพน้อยกว่า Scala ที่เทียบเท่ากัน ในขณะที่มีโอกาสในการปรับปรุง (มีการพัฒนาอย่างมากใน Spark 2.0.0) ข้อ จำกัด ที่ใหญ่ที่สุดคือการไปกลับเต็มรูปแบบระหว่างการเป็นตัวแทนภายใน (JVM) และล่าม Python หากเป็นไปได้คุณควรสนับสนุนองค์ประกอบของนิพจน์ในตัว ( เช่นพฤติกรรม Python UDF ได้รับการปรับปรุงใน Spark 2.0.0 แต่ยังคงดีกว่าเมื่อเทียบกับการประมวลผลแบบเนทีฟ

สิ่งนี้อาจปรับปรุงในอนาคตได้ดีขึ้นอย่างมีนัยสำคัญด้วยการเปิดตัวvectorized UDFs (SPARK-21190 และส่วนขยายเพิ่มเติม)ซึ่งใช้ Arrow Streaming สำหรับการแลกเปลี่ยนข้อมูลที่มีประสิทธิภาพด้วยการกำจัดสำเนาแบบไม่มีศูนย์ สำหรับแอปพลิเคชันส่วนใหญ่ค่าโสหุ้ยรองของพวกเขาสามารถถูกละเว้นได้

นอกจากนี้จะต้องแน่ใจว่าจะหลีกเลี่ยงการผ่านข้อมูลที่ไม่จำเป็นระหว่างและDataFrames RDDsสิ่งนี้ต้องการการทำให้เป็นอนุกรมและการดีซีเรียลไลเซชั่นที่มีราคาแพงไม่ต้องพูดถึงการถ่ายโอนข้อมูลไปและกลับจากล่าม Python

เป็นที่น่าสังเกตว่าสาย Py4J นั้นมีความหน่วงแฝงค่อนข้างสูง ซึ่งรวมถึงการโทรง่าย ๆ เช่น:

from pyspark.sql.functions import col

col("foo")

โดยปกติแล้วมันไม่สำคัญ (ค่าใช้จ่ายคงที่และไม่ได้ขึ้นอยู่กับปริมาณข้อมูล) แต่ในกรณีของแอปพลิเคชันแบบเรียลไทม์คุณอาจพิจารณาใช้แคช / นำชุดคลุมข้อมูล Java มาใช้ซ้ำ

ชุดข้อมูล GraphX ​​และ Spark

สำหรับตอนนี้ (Spark 1.6 2.1) ไม่มีใครให้ PySpark API ดังนั้นคุณสามารถพูดได้ว่า PySpark นั้นแย่กว่า Scala

GraphX

ในทางปฏิบัติการพัฒนา GraphX หยุดเกือบสมบูรณ์และโครงการขณะนี้อยู่ในโหมดการบำรุงรักษาที่มีเกี่ยวข้องตั๋ว JIRA ปิดจะไม่แก้ไข ไลบรารีGraphFramesจัดเตรียมไลบรารีการประมวลผลกราฟทางเลือกที่มีการโยง Python

ชุด

ผู้กระทำการพูดที่มีอยู่ไม่มากสถานที่สำหรับการพิมพ์แบบคงที่ในหลามและแม้ว่าจะมีการดำเนินงานกาลาปัจจุบันคือง่ายเกินไปและไม่ได้ให้ผลประโยชน์เช่นเดียวกับDatasetsDataFrame

สตรีมมิ่ง

จากสิ่งที่ฉันเห็นมาฉันขอแนะนำให้ใช้ Scala มากกว่า Python อาจมีการเปลี่ยนแปลงในอนาคตหาก PySpark ได้รับการสนับสนุนสำหรับสตรีมที่มีโครงสร้าง แต่ตอนนี้ Scala API ดูเหมือนจะแข็งแกร่งกว่ามีความครอบคลุมและมีประสิทธิภาพมากขึ้น ประสบการณ์ของฉันค่อนข้าง จำกัด

การสตรีมแบบมีโครงสร้างใน Spark 2.x ดูเหมือนจะลดช่องว่างระหว่างภาษา แต่ตอนนี้มันยังอยู่ในช่วงแรก ๆ อย่างไรก็ตาม API ที่ใช้ RDD นั้นถูกอ้างอิงเป็น "การสตรีมแบบดั้งเดิม" ในเอกสาร Databricks (วันที่เข้าถึง 2017-03-03) ดังนั้นจึงสมเหตุสมผลที่จะคาดหวังความพยายามในการรวมกันเพิ่มเติม

ข้อควรพิจารณาเกี่ยวกับประสิทธิภาพที่ไม่ใช่

ความเท่าเทียมกันของคุณสมบัติ

คุณสมบัติ Spark ทั้งหมดนั้นไม่ได้เปิดเผยผ่าน PySpark API ตรวจสอบให้แน่ใจว่าชิ้นส่วนที่คุณต้องการมีการใช้งานแล้วและพยายามเข้าใจข้อ จำกัด ที่เป็นไปได้

เป็นสิ่งสำคัญอย่างยิ่งเมื่อคุณใช้ MLlib และบริบทผสมที่คล้ายกัน (ดูที่การเรียกฟังก์ชัน Java / Scala จากงาน ) เพื่อให้เกิดความยุติธรรมบางส่วนของ PySpark API mllib.linalgจะให้วิธีการที่ครอบคลุมกว่า Scala

การออกแบบ API

PySpark API สะท้อนให้เห็นถึงคู่ของ Scala อย่างใกล้ชิดและไม่ได้เป็น Pythonic หมายความว่ามันง่ายที่จะแมประหว่างภาษา แต่ในเวลาเดียวกันรหัส Python อาจเข้าใจยาก

สถาปัตยกรรมที่ซับซ้อน

การไหลของข้อมูล PySpark ค่อนข้างซับซ้อนเมื่อเทียบกับการดำเนินการ JVM บริสุทธิ์ เป็นการยากที่จะให้เหตุผลเกี่ยวกับโปรแกรมหรือดีบัก PySpark นอกจากนี้ความเข้าใจพื้นฐานอย่างน้อยเกี่ยวกับ Scala และ JVM โดยทั่วไปนั้นเป็นสิ่งที่ต้องมี

Spark 2.x และสูงกว่า

การเปลี่ยนไปใช้DatasetAPI อย่างต่อเนื่องพร้อมกับ RDD API ที่แช่แข็งนำทั้งโอกาสและความท้าทายสำหรับผู้ใช้ Python ในขณะที่ชิ้นส่วนระดับสูงของ API เป็นเรื่องง่ายที่จะเปิดเผยในหลามที่คุณสมบัติที่สูงขึ้นจะสวยไปไม่ได้มากที่จะนำมาใช้โดยตรง

ยิ่งไปกว่านั้นฟังก์ชั่น Python ดั้งเดิมยังคงเป็นพลเมืองชั้นสองในโลก SQL หวังว่าสิ่งนี้จะปรับปรุงในอนาคตด้วยการทำอนุกรม Apache Arrow ( ข้อมูลเป้าหมายความพยายามในปัจจุบันcollectionแต่ UDF serde เป็นเป้าหมายระยะยาว )

สำหรับโครงการที่ขึ้นอยู่กับ Python codebase ทางเลือก Python ล้วน ๆ (เช่นDaskหรือRay ) อาจเป็นทางเลือกที่น่าสนใจ

มันไม่จำเป็นต้องเป็นหนึ่งกับอื่น ๆ

Spark DataFrame (SQL, Dataset) API เป็นวิธีการที่ยอดเยี่ยมในการรวมโค้ด Scala / Java ในแอปพลิเคชัน PySpark คุณสามารถใช้DataFramesเพื่อเปิดเผยข้อมูลไปยังรหัส JVM ดั้งเดิมและอ่านผลลัพธ์ ผมได้อธิบายตัวเลือกบางอย่างที่อื่นและคุณสามารถหาตัวอย่างการทำงานของงูใหญ่-Scala บินตั้งอยู่ในวิธีการใช้ระดับ Scala ภายใน Pyspark

สามารถเพิ่มเพิ่มเติมได้โดยการแนะนำประเภทที่กำหนดโดยผู้ใช้ (ดูที่วิธีกำหนดสคีมาสำหรับประเภทที่กำหนดเองใน Spark SQL? )


มีอะไรผิดปกติกับรหัสที่ให้ไว้ในคำถาม

(ข้อจำกัดความรับผิดชอบ: มุมมอง Pythonista มีแนวโน้มมากที่ฉันพลาดเทคนิค Scala)

ก่อนอื่นมีส่วนหนึ่งในรหัสของคุณซึ่งไม่สมเหตุสมผลเลย หากคุณมี(key, value)คู่ที่สร้างขึ้นโดยใช้zipWithIndexหรือenumerateสิ่งที่เป็นจุดในการสร้างสตริงเพียงเพื่อแยกมันในภายหลัง? flatMapไม่ทำงานซ้ำ ๆ เพื่อให้คุณสามารถให้สิ่งอันดับและข้ามไปติดตามmapใด ๆ

reduceByKeyอีกส่วนหนึ่งผมพบว่ามีปัญหาคือ โดยทั่วไปการพูดreduceByKeyจะมีประโยชน์หากการใช้ฟังก์ชั่นรวมสามารถลดจำนวนข้อมูลที่จะต้องสับ เมื่อคุณเชื่อมโยงสตริงเข้าด้วยกันจึงไม่มีอะไรให้ได้รับที่นี่ groupByKeyละเว้นสิ่งที่ระดับต่ำเช่นจำนวนการอ้างอิงจำนวนของข้อมูลที่คุณมีในการถ่ายโอนเป็นสิ่งเดียวกับ

ปกติฉันจะไม่อยู่บนนั้น แต่เท่าที่ฉันสามารถบอกได้ว่ามันเป็นคอขวดในโค้ดสกาล่าของคุณ การรวมสตริงใน JVM เป็นการดำเนินการที่ค่อนข้างแพง (ดูตัวอย่าง: การต่อสตริงในสกาล่ามีราคาแพงเหมือนในจาวาหรือไม่ ) หมายความว่าบางสิ่งเช่นนี้_.reduceByKey((v1: String, v2: String) => v1 + ',' + v2) ซึ่งเทียบเท่ากับinput4.reduceByKey(valsConcat)ในโค้ดของคุณไม่ใช่ความคิดที่ดี

หากคุณต้องการที่จะหลีกเลี่ยงgroupByKeyคุณสามารถพยายามที่จะใช้กับaggregateByKey StringBuilderสิ่งที่คล้ายกับสิ่งนี้ควรทำเคล็ดลับ:

rdd.aggregateByKey(new StringBuilder)(
  (acc, e) => {
    if(!acc.isEmpty) acc.append(",").append(e)
    else acc.append(e)
  },
  (acc1, acc2) => {
    if(acc1.isEmpty | acc2.isEmpty)  acc1.addString(acc2)
    else acc1.append(",").addString(acc2)
  }
)

แต่ฉันสงสัยว่ามันมีค่าเอะอะทั้งหมด

เมื่อคำนึงถึงข้างต้นฉันได้เขียนโค้ดของคุณใหม่ดังนี้:

สกาล่า :

val input = sc.textFile("train.csv", 6).mapPartitionsWithIndex{
  (idx, iter) => if (idx == 0) iter.drop(1) else iter
}

val pairs = input.flatMap(line => line.split(",").zipWithIndex.map{
  case ("true", i) => (i, "1")
  case ("false", i) => (i, "0")
  case p => p.swap
})

val result = pairs.groupByKey.map{
  case (k, vals) =>  {
    val valsString = vals.mkString(",")
    s"$k,$valsString"
  }
}

result.saveAsTextFile("scalaout")

งูหลาม :

def drop_first_line(index, itr):
    if index == 0:
        return iter(list(itr)[1:])
    else:
        return itr

def separate_cols(line):
    line = line.replace('true', '1').replace('false', '0')
    vals = line.split(',')
    for (i, x) in enumerate(vals):
        yield (i, x)

input = (sc
    .textFile('train.csv', minPartitions=6)
    .mapPartitionsWithIndex(drop_first_line))

pairs = input.flatMap(separate_cols)

result = (pairs
    .groupByKey()
    .map(lambda kv: "{0},{1}".format(kv[0], ",".join(kv[1]))))

result.saveAsTextFile("pythonout")

ผล

ในlocal[6]โหมด (Intel (R) Xeon (R) CPU E3-1245 V2 @ 3.40GHz) ที่มีหน่วยความจำ 4GB ต่อผู้ดำเนินการที่ใช้ (n = 3):

  • สกาล่า - หมายถึง: 250.00s, มาตรฐาน: 12.49
  • Python - หมายถึง: 246.66s, stdev: 1.15

ฉันค่อนข้างแน่ใจว่าเวลาส่วนใหญ่จะใช้ในการสับการทำให้เป็นอนุกรม, ดีซีเรียลไลซิ่งและงานรองอื่น ๆ เพื่อความสนุกนี่เป็นโค้ดที่ไม่ต้องใช้เกลียวใน Python ที่ทำงานแบบเดียวกันกับเครื่องนี้ในเวลาไม่ถึงนาที:

def go():
    with open("train.csv") as fr:
        lines = [
            line.replace('true', '1').replace('false', '0').split(",")
            for line in fr]
    return zip(*lines[1:])

23
หนึ่งในคำตอบที่ชัดเจนครอบคลุมและมีประโยชน์ที่สุดที่ฉันได้พบมาระยะหนึ่งแล้ว ขอบคุณ!
etov

ช่างเป็นคนที่ยอดเยี่ยมจริงๆ!
DennisLi

-4

ขยายไปสู่คำตอบข้างต้น -

สกาล่าพิสูจน์ได้เร็วกว่าในหลาย ๆ ทางเมื่อเทียบกับงูหลาม แต่มีเหตุผลบางประการที่ทำให้งูหลามได้รับความนิยมมากขึ้นเรื่อย ๆ

Python สำหรับ Apache Spark นั้นง่ายต่อการเรียนรู้และใช้งาน อย่างไรก็ตามนี่ไม่ใช่เหตุผลเดียวที่ Pyspark เป็นตัวเลือกที่ดีกว่า Scala ยังมีอีก.

Python API สำหรับ Spark อาจช้าลงในคลัสเตอร์ แต่ท้ายที่สุดนักวิทยาศาสตร์ข้อมูลสามารถทำอะไรได้มากกว่านี้มากเมื่อเทียบกับ Scala ความซับซ้อนของสกาล่าขาดไป อินเทอร์เฟซง่ายและครอบคลุม

การพูดถึงความสามารถในการอ่านรหัสการบำรุงรักษาและความคุ้นเคยกับ Python API สำหรับ Apache Spark นั้นดีกว่า Scala

Python มาพร้อมกับห้องสมุดหลายแห่งที่เกี่ยวข้องกับการเรียนรู้ของเครื่องและการประมวลผลภาษาธรรมชาติ สิ่งนี้ช่วยในการวิเคราะห์ข้อมูลและยังมีสถิติที่มีความเป็นผู้ใหญ่มากและมีการทดสอบเวลา ตัวอย่างเช่น numpy, pandas, scikit-learn, seaborn และ matplotlib

หมายเหตุ: นักวิทยาศาสตร์ข้อมูลส่วนใหญ่ใช้วิธีไฮบริดที่พวกเขาใช้ API ที่ดีที่สุด

สุดท้ายชุมชน Scala มักจะกลายเป็นประโยชน์น้อยมากกับโปรแกรมเมอร์ สิ่งนี้ทำให้ Python เรียนรู้ที่มีค่ามาก หากคุณมีประสบการณ์เพียงพอกับภาษาการเขียนโปรแกรมแบบคงที่เช่น Java คุณสามารถหยุดกังวลเกี่ยวกับการไม่ใช้ Scala ทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.