স্পার্ক: পাইথন আমার ব্যবহারের ক্ষেত্রে স্ক্যালাকে উল্লেখযোগ্যভাবে ছাড়িয়ে যায় কেন?


16

পাইথন এবং স্কালা ব্যবহার করার সময় স্পার্কের পারফরম্যান্সের তুলনা করতে আমি উভয় ভাষায় একই কাজ তৈরি করেছি এবং রানটাইম তুলনা করেছি। আমি উভয় চাকরিই প্রায় একই পরিমাণে সময় নেওয়ার প্রত্যাশা করেছিল, তবে পাইথন 27minচাকরীটি কেবল গ্রহণ করেছিল , যখন স্কালার কাজটি 37min(প্রায় ৪০% বেশি সময়!) নিয়েছিল । আমি জাভাতেও একই কাজটি প্রয়োগ করেছি এবং এটিও গ্রহণ 37minutesকরেছে। পাইথন এত দ্রুত যে কীভাবে সম্ভব?

ন্যূনতম যাচাইযোগ্য উদাহরণ:

পাইথনের কাজ:

# Configuration
conf = pyspark.SparkConf()
conf.set("spark.hadoop.fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
conf.set("spark.executor.instances", "4")
conf.set("spark.executor.cores", "8")
sc = pyspark.SparkContext(conf=conf)

# 960 Files from a public dataset in 2 batches
input_files = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312025.20/warc/CC-MAIN-20190817203056-20190817225056-00[0-5]*"
input_files2 = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312128.3/warc/CC-MAIN-20190817102624-20190817124624-00[0-3]*"

# Count occurances of a certain string
logData = sc.textFile(input_files)
logData2 = sc.textFile(input_files2)
a = logData.filter(lambda value: value.startswith('WARC-Type: response')).count()
b = logData2.filter(lambda value: value.startswith('WARC-Type: response')).count()

print(a, b)

স্কাল কাজ:

// Configuration
config.set("spark.executor.instances", "4")
config.set("spark.executor.cores", "8")
val sc = new SparkContext(config)
sc.setLogLevel("WARN")
sc.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")

// 960 Files from a public dataset in 2 batches 
val input_files = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312025.20/warc/CC-MAIN-20190817203056-20190817225056-00[0-5]*"
val input_files2 = "s3a://commoncrawl/crawl-data/CC-MAIN-2019-35/segments/1566027312128.3/warc/CC-MAIN-20190817102624-20190817124624-00[0-3]*"

// Count occurances of a certain string
val logData1 = sc.textFile(input_files)
val logData2 = sc.textFile(input_files2)
val num1 = logData1.filter(line => line.startsWith("WARC-Type: response")).count()
val num2 = logData2.filter(line => line.startsWith("WARC-Type: response")).count()

println(s"Lines with a: $num1, Lines with b: $num2")

কেবল কোডটি দেখে তারা দেখতে অভিন্ন বলে মনে হচ্ছে। আমি একটি ডিএজিগুলি দেখেছি এবং তারা কোনও অন্তর্দৃষ্টি দেয় নি (বা তাদের উপর ভিত্তি করে ব্যাখ্যা দিয়ে কীভাবে আসতে হবে তা সম্পর্কে আমার জানা-জ্ঞানের অভাব রয়েছে)।

আমি সত্যিই কোন পয়েন্টার প্রশংসা করব।


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
স্যামুয়েল লিউ

1
অজগর সংস্করণটি আরও দ্রুত আছে এমন কোনও নির্দিষ্ট জায়গা রয়েছে কিনা তা দেখার জন্য আমি সংশ্লিষ্ট ব্লকগুলি এবং বিবৃতিগুলির সময় নির্ধারণ করে কিছু জিজ্ঞাসার আগে বিশ্লেষণটি শুরু করেছিলাম। তাহলে আপনি 'এই অজগর বিবৃতিটি কেন দ্রুত' এ প্রশ্নটি তীক্ষ্ণ করতে সক্ষম হবেন।
টেরি জন রেডি

উত্তর:


11

আপনার বেসিক অনুমান, স্কেলা বা জাভা এই নির্দিষ্ট কাজের জন্য দ্রুত হওয়া উচিত, এটি ঠিক ভুল। আপনি এটি নূন্যতম স্থানীয় অ্যাপ্লিকেশন সহ সহজেই যাচাই করতে পারেন। স্কেল এক:

import scala.io.Source
import java.time.{Duration, Instant}

object App {
  def main(args: Array[String]) {
    val Array(filename, string) = args

    val start = Instant.now()

    Source
      .fromFile(filename)
      .getLines
      .filter(line => line.startsWith(string))
      .length

    val stop = Instant.now()
    val duration = Duration.between(start, stop).toMillis
    println(s"${start},${stop},${duration}")
  }
}

পাইথন এক

import datetime
import sys

if __name__ == "__main__":
    _, filename, string = sys.argv
    start = datetime.datetime.now()
    with open(filename) as fr:
        # Not idiomatic or the most efficient but that's what
        # PySpark will use
        sum(1 for _ in filter(lambda line: line.startswith(string), fr))

    end = datetime.datetime.now()
    duration = round((end - start).total_seconds() * 1000)
    print(f"{start},{end},{duration}")

হার্মিনিউটিক্স.স্ট্যাকেক্সেক্সঞ্জ ডটকমের ডেটা ডাম্প ম্যাচিং এবং অ মেলানো নিদর্শনগুলির মিশ্রণ সহ ফলাফল (প্রতিটির 300 টি পুনরাবৃত্তি, পাইথন 3.7.6, স্কেলা 2.11.12) Posts.xmlথেকে প্রাপ্ত :

উপরের প্রোগ্রামগুলির জন্য মিলিসে দুরারেশন বক্সপ্লট

  • পাইথন 273.50 (258.84, 288.16)
  • স্কালা 634.13 (533.81, 734.45)

আপনি দেখতে পাই পাইথন কেবল নিয়মিতভাবেই দ্রুততর হয় না, তবে এটি আরও সুসংগত (নিম্ন স্প্রেড)।

টেক অফ বার্তাটি হ'ল - অসমর্থিত এফইউডি বিশ্বাস করবেন না - নির্দিষ্ট কাজগুলিতে বা নির্দিষ্ট পরিবেশের সাথে ভাষাগুলি দ্রুত বা ধীর হতে পারে (উদাহরণস্বরূপ এখানে স্কালা জেভিএম স্টার্টআপ এবং / অথবা জিসি এবং / বা জেআইটি দ্বারা আঘাত করা যেতে পারে), তবে আপনি যদি দাবি করেন "এক্সওয়াইজেড এক্স এক্স দ্রুততর" বা "জাইওয়াইএস (..) এর তুলনায়" এক্সওয়াইজেড ধীর গতিতে প্রায় 10x ধীর "এর অর্থ সাধারণত কেউ বোঝায় যে জিনিস পরীক্ষা করার জন্য কেউ সত্যই খারাপ কোড লিখেছিল।

সম্পাদনা করুন :

মন্তব্যে উত্থাপিত কিছু উদ্বেগের সমাধান করতে:

  • ওপি কোডে ডেটা বেশিরভাগ একদিকে (JVM -> পাইথন) পাস করা হয় এবং কোনও সত্যিক সিরিয়ালাইজেশন প্রয়োজন হয় না (এই নির্দিষ্ট পাথটি কেবল বাইট্রেটিং পাশ করে এবং অন্যদিকে ইউটিএফ -8 এ ডিকোড করে)। "সিরিয়ালাইজেশন" এর ক্ষেত্রে এটি যতটা সস্তা তা পাওয়া যায়।
  • পার্টিশন অনুসারে যা যা পাস হবে তা কেবল একটি একক পূর্ণসংখ্যার, সুতরাং সেই দিকটিতে প্রভাব তুচ্ছ।
  • স্থানীয় সকেটে যোগাযোগ করা হয় (প্রাথমিক সংযোগের বাইরে কর্মীদের উপর সমস্ত যোগাযোগ এবং প্রমাণীকরণ থেকে ফিরে আসা ফাইল বর্ণনাকারী ব্যবহার করে সম্পাদন করা হয় local_connect_and_authএবং এটি সকেট সম্পর্কিত ফাইল ছাড়া আর কিছুই নয় )। আবার প্রক্রিয়াগুলির মধ্যে যোগাযোগের ক্ষেত্রে এটি যতটা সস্তা তা পাওয়া যায়।
  • উপরে প্রদর্শিত কাঁচা পারফরম্যান্সের পার্থক্যের কথা বিবেচনা করে (আপনি আপনার প্রোগ্রামে যা দেখছেন তার থেকে অনেক বেশি) উপরে বর্ণিত ওভারহেডগুলির জন্য প্রচুর মার্জিন রয়েছে।
  • এই কেসগুলি সম্পূর্ণরূপে পৃথক, যেখানে সরল বা জটিল বস্তুগুলিকে পাইথন ইন্টারপ্রেটারের কাছে ফর্ম হিসাবে পাঠাতে হয় যা উভয় পক্ষের কাছে আচার-সামঞ্জস্যপূর্ণ ডাম্প হিসাবে অ্যাক্সেসযোগ্য হয় (সর্বাধিক উল্লেখযোগ্য উদাহরণগুলিতে পুরানো স্টাইলের ইউডিএফ অন্তর্ভুক্ত রয়েছে, পুরানো কিছু অংশ -স্টাইল এমএলিব)।

সম্পাদনা 2 :

যেহেতু জ্যাস্পার-এম এখানে স্টার্টআপ ব্যয়ের বিষয়ে উদ্বিগ্ন ছিল তাই সহজেই প্রমাণ করা যায় যে ইনপুট আকারটি উল্লেখযোগ্য পরিমাণে বাড়ানো সত্ত্বেও পাইথনের স্ক্যালালের তুলনায় এখনও পাইথনের উল্লেখযোগ্য সুবিধা রয়েছে।

এখানে 2003360 লাইন / 5.6 জি (একই ইনপুট, কেবলমাত্র একাধিক বার নকল করা হয়েছে, 30 পুনরাবৃত্তি) এর ফলাফল রয়েছে, যা কোনও একক স্পার্ক টাস্কে আপনি আশা করতে পারেন এমন কোনও ছাড়িয়ে যায়।

এখানে চিত্র বর্ণনা লিখুন

  • পাইথন 22809.57 (21466.26, 24152.87)
  • স্কালা 27315.28 (24367.24, 30263.31)

অনুগ্রহ করে অ-ওভারল্যাপিং আত্মবিশ্বাসের অন্তরগুলি নোট করুন।

সম্পাদনা 3 :

মোকাবেলার অন্য মন্তব্য জ্যাসপার-M থেকে:

সমস্ত প্রসেসিংয়ের সিংহভাগ এখনও স্পার্ক ক্ষেত্রে একটি জেভিএম-এর অভ্যন্তরে ঘটছে।

এই বিশেষ ক্ষেত্রে এটি সহজভাবে ভুল:

  • প্রশ্নে থাকা কাজটি হল পাইপ স্পার্ক আরডিডি ব্যবহার করে একক বিশ্বব্যাপী মানচিত্রের কাজ।
  • পাইস্পার্ক আরডিডি (আসুন আমরা বলি নয় DataFrame) ব্যতিক্রমী ইনপুট, আউটপুট এবং আন্তঃ নোড যোগাযোগের মাধ্যমে পাইথনে স্থানীয়ভাবে কার্যকারিতার স্থূল প্রয়োগ করে।
  • যেহেতু এটি একক পর্যায়ের কাজ, এবং চূড়ান্ত আউটপুট এড়িয়ে যাওয়া যথেষ্ট ছোট, জেভিএমের প্রধান দায়িত্ব (যদি কেউ নিতপিক হয় তবে এটি বেশিরভাগ জাভাতে প্রয়োগ করা হত না স্কালায়) হাদুপ ইনপুট ফর্ম্যাটটি আহ্বান করা, এবং সকেটের মাধ্যমে ডেটা পুশ করা পাইথন ফাইল।
  • পঠিত অংশটি জেভিএম এবং পাইথন এপিআইয়ের জন্য অভিন্ন, সুতরাং এটি ধ্রুবক ওভারহেড হিসাবে বিবেচনা করা যেতে পারে। এটি প্রসেসিংয়ের সর্বাধিক হিসাবে যোগ্যতা অর্জন করে না , এমনকি এই জাতীয় মতো সাধারণ কাজের জন্যও।

3
সমস্যার চমৎকার পদ্ধতির। এটি ভাগ করে নেওয়ার জন্য আপনাকে ধন্যবাদ
আলেকজান্দ্রোস বিরাটসিস

1
@ ইগোর্দো আলেকজান্দ্রোস বলেছিলেন যে "এখানে কোনও ইউডিএফ আহবান করা হয়নি" এমন নয় যে "পাইথনটি চাওয়া হয়নি" - যা সমস্ত পার্থক্য তৈরি করে। সিস্টেমের মধ্যে ডেটা আদান প্রদান করা হয় যেখানে সিরিয়ালাইজেশন ওভারহেড গুরুত্বপূর্ণ (যেমন আপনি যখন কোনও ইউডিএফ এবং পিছনে ডেটা প্রেরণ করতে চান তখন)।
ব্যবহারকারী 10938362

1
@ ইগোর্দো আপনি দুটি বিষয় পরিষ্কারভাবে বিভ্রান্ত করেছেন - সিরিয়ালাইজেশনের ওভারহেড, এটি এমন সমস্যা যেখানে অ-তুচ্ছ বস্তুগুলি সামনে এবং পিছনে পাস করা হয়। এবং যোগাযোগের ওভারহেড। এখানে খুব কম বা কোনও সিরিয়ালাইজেশন ওভারহেড নেই, কারণ আপনি কেবলই বাইটস্ট্রিংগুলি পাস এবং ডিকোড করেন এবং এটি বেশিরভাগ দিকনির্দেশে ঘটে, যেমন আপনি প্রতি পার্টিশনটিতে একক পূর্ণসংখ্যা পান। যোগাযোগ কিছুটা উদ্বেগের বিষয়, তবে আন্তঃ-প্রক্রিয়া সংযোগের ক্ষেত্রে স্থানীয় সকেটের মাধ্যমে ডেটা পাস করা কার্যকরী কারণ এটি সত্যই পাওয়া যায়। যদি এটি পরিষ্কার না হয় তবে আমি উত্সটি পড়ার পরামর্শ দিচ্ছি - এটি কঠিন নয় এবং আলোকিত করা হবে।
ব্যবহারকারী 10938362

1
অতিরিক্তভাবে সিরিয়ালাইজেশন পদ্ধতিগুলি কেবল সমান করা হয় না। যেমন স্পার্ক কেস দেখায় ভাল সিরিয়ালাইজেশন পদ্ধতিগুলি স্তরের ব্যয়কে হ্রাস করতে পারে যেখানে এটি আর উদ্বেগের বিষয় নয় (তীরের সাথে পান্ডাস ইউডিএফ দেখুন) এবং যখন এটি ঘটে তখন অন্যান্য বিষয়গুলি প্রভাব ফেলতে পারে (উদাহরণস্বরূপ স্কালাল উইন্ডো ফাংশনগুলির মধ্যে পারফরম্যান্সের তুলনা এবং পান্ডাদের সাথে তার সমতুল্যতা দেখুন) ইউডিএফস - এই প্রশ্নের চেয়ে পাইথন সেখানে অনেক বেশি মার্জিনের সাথে জিতেছে)।
ব্যবহারকারী 10938362

1
এবং আপনার বক্তব্যটি @ জ্যাস্পার-এম? স্বতন্ত্র স্পার্ক কাজগুলি এর সাথে তুলনীয় কাজের চাপ রাখার জন্য যথেষ্ট ছোট। আমাকে ভুল পথে নিয়ে যাবেন না, তবে আপনার যদি এমন কোনও প্রকৃত পাল্টা নমুনা থাকে যা এই বা পুরো প্রশ্নটিকে অবৈধ করে দেয় তবে দয়া করে এটি পোস্ট করুন। আমি ইতিমধ্যে লক্ষ করেছি যে গৌণ ক্রিয়াকলাপগুলি এই মানটিতে কিছুটা অবদান রাখে, তবে তারা ব্যয়কে প্রভাবিত করে না। আমরা এখানে সমস্ত প্রকৌশলী (একধরনের) - আসুন নম্বর এবং কোড কথা বলি, বিশ্বাস নয়, আমরা কি করব?
ব্যবহারকারী 10938362

4

স্কালার কাজটি বেশি সময় নেয় কারণ এটির একটি ভুল কনফিগারেশন রয়েছে এবং তাই পাইথন এবং স্কালার কাজগুলিকে অসম সম্পদ সরবরাহ করা হয়েছিল।

কোডটিতে দুটি ভুল রয়েছে:

val sc = new SparkContext(config) // LINE #1
sc.setLogLevel("WARN")
sc.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")
sc.hadoopConfiguration.set("spark.executor.instances", "4") // LINE #4
sc.hadoopConfiguration.set("spark.executor.cores", "8") // LINE #5
  1. লাইন 1. লাইনটি কার্যকর হয়ে গেলে স্পার্ক জবের রিসোর্স কনফিগারেশনটি ইতিমধ্যে প্রতিষ্ঠিত এবং ঠিক হয়ে গেছে। এই দিক থেকে, কোনও কিছুর সামঞ্জস্য করার উপায় নেই। নির্বাহকের সংখ্যা বা নির্বাহকের জন্য কোরগুলির সংখ্যাও নয়।
  2. লাইন 4-5। sc.hadoopConfigurationকোনও স্পার্ক কনফিগারেশন সেট করার জন্য এটি একটি ভুল জায়গা। আপনি যে configপরিস্থিতিতে যাচ্ছেন সেটি সেট করা উচিত new SparkContext(config)

[যোগ করুন] উপরের বিষয়টি মাথায় রেখে আমি স্কালার কাজের কোডটি পরিবর্তনের প্রস্তাব করব

config.set("spark.executor.instances", "4")
config.set("spark.executor.cores", "8")
val sc = new SparkContext(config) // LINE #1
sc.setLogLevel("WARN")
sc.hadoopConfiguration.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.AnonymousAWSCredentialsProvider")

এবং এটি আবার পরীক্ষা করুন। আমি বাজি ধরছি স্কালাল সংস্করণটি এখন এক্স গুণ দ্রুত হতে চলেছে।


আমি যাচাই করেছি যে উভয় কাজই সমান্তরালভাবে 32 টি কাজ চালায় তাই আমি মনে করি না যে এই অপরাধী?
maestromusica

সম্পাদনার জন্য ধন্যবাদ, এখনই এটি পরীক্ষা করার চেষ্টা করবে
maestromusica

হাই @ মায়স্ট্রোমিউজিক এটি অবশ্যই রিসোর্স কনফিগারেশনের কিছু হতে পারে কারণ অভ্যন্তরীণভাবে পাইথন এই বিশেষ ব্যবহারের ক্ষেত্রে স্কালকে ছাড়িয়ে যেতে পারে না। আর একটি কারণ হতে পারে কিছু অসামঞ্জস্যিত এলোমেলো কারণ, যেমন নির্দিষ্ট মুহুর্তে ক্লাস্টারের বোঝা এবং অনুরূপ। বিটিডব্লিউ, আপনি কোন মোড ব্যবহার করেন? একক, স্থানীয়, সুতা?
egordoe

হ্যাঁ, আমি যাচাই করেছি যে এই উত্তরটি ভুল। রানটাইম একই। আমি উভয় ক্ষেত্রেই কনফিগারেশনটি মুদ্রণ করেছি এবং এটি অভিন্ন।
maestromusica

1
আমি মনে করি আপনি ঠিক থাকতে পারেন। আমি এই প্রশ্নটি অন্য সমস্ত সম্ভাবনা যেমন কোডের ভুল বা সম্ভবত কিছু ভুল বুঝেছিলাম তা তদন্ত করতে বলেছিলাম। আপনার ইনপুট জন্য ধন্যবাদ।
maestromusica
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.