কিভাবে স্পার্ক এক্সিকিউটারের নম্বর, কোর এবং এক্সিকিউটার মেমরি টিউন করবেন?


84

আপনি উল্লিখিত প্যারামগুলি টিউন করতে কোথায় শুরু করবেন। আমরা কি এক্সিকিউটারের মেমোরি দিয়ে শুরু করি এবং এক্সিকিউটারের সংখ্যা পাই, বা আমরা কোর দিয়ে শুরু করি এবং এক্সিকিউটারের নম্বর পাই। আমি লিঙ্কটি অনুসরণ করেছিলাম । তবে একটি উচ্চ স্তরের ধারণা পেয়েছে তবে এখনও কীভাবে বা কোথায় শুরু হবে এবং চূড়ান্ত সিদ্ধান্তে পৌঁছতে হবে তা এখনও নিশ্চিত নয়।

উত্তর:


210

নিম্নলিখিত উত্তরটি শিরোনামে উল্লিখিত তিনটি প্রধান দিককে অন্তর্ভুক্ত করে - নির্বাহকের সংখ্যা, এক্সিকিউটারের স্মৃতি এবং কোর সংখ্যা। ড্রাইভারের মেমরির মতো অন্যান্য পরামিতি এবং অন্যান্য থাকতে পারে যা আমি এই উত্তর হিসাবে সম্বোধন করি নি, তবে নিকট ভবিষ্যতে যুক্ত করতে চাই।

কেস 1 হার্ডওয়্যার - 6 নোড এবং প্রতিটি নোড 16 কোর, 64 জিবি র‌্যাম

প্রতিটি নির্বাহক একটি জেভিএম উদাহরণ। সুতরাং আমরা একক নোডে একাধিক এক্সিকিউটার থাকতে পারি

ওএস এবং হ্যাডোপ ডেমনসের জন্য প্রথম 1 কোর এবং 1 জিবি প্রয়োজন, তাই প্রতিটি নোডের জন্য 15 টি কোর, 63 জিবি র‌্যাম পাওয়া যায়

কোরগুলির সংখ্যা কীভাবে চয়ন করবেন তা দিয়ে শুরু করুন :

Number of cores = Concurrent tasks as executor can run 

So we might think, more concurrent tasks for each executor will give better performance. But research shows that
any application with more than 5 concurrent tasks, would lead to bad show. So stick this to 5.

This number came from the ability of executor and not from how many cores a system has. So the number 5 stays same
even if you have double(32) cores in the CPU.

নির্বাহকের সংখ্যা:

Coming back to next step, with 5 as cores per executor, and 15 as total available cores in one Node(CPU) - we come to 
3 executors per node.

So with 6 nodes, and 3 executors per node - we get 18 executors. Out of 18 we need 1 executor (java process) for AM in YARN we get 17 executors

This 17 is the number we give to spark using --num-executors while running from spark-submit shell command

প্রতিটি নির্বাহকের জন্য স্মৃতি:

From above step, we have 3 executors  per node. And available RAM is 63 GB

So memory for each executor is 63/3 = 21GB. 

However small overhead memory is also needed to determine the full memory request to YARN for each executor.
Formula for that over head is max(384, .07 * spark.executor.memory)

Calculating that overhead - .07 * 21 (Here 21 is calculated as above 63/3)
                            = 1.47

Since 1.47 GB > 384 MB, the over head is 1.47.
Take the above from each 21 above => 21 - 1.47 ~ 19 GB

So executor memory - 19 GB

চূড়ান্ত সংখ্যা - এক্সিকিউটর - 17, কোর 5, এক্সিকিউটার মেমরি - 19 জিবি


কেস 2 হার্ডওয়্যার: একই 6 নোড, 32 কোর, 64 জিবি

5 ভাল সমঝোতার জন্য একই

প্রতিটি নোডের জন্য নির্বাহকের সংখ্যা = 32/5 ~ 6

সুতরাং মোট নির্বাহক = 6 * 6 নোড = 36. তারপরে চূড়ান্ত সংখ্যা 36 - 1 এএম = 35 এর জন্য

এক্সিকিউটারের মেমরিটি: প্রতিটি নোডের জন্য 6 জন এক্সিকিউটর। 63/6। 10। ওভার হেড .07 * 10 = 700 এমবি। ওভার হেড হিসাবে 1GB তে গোল করে আমরা 10-1 = 9 জিবি পাই

চূড়ান্ত সংখ্যা - নির্বাহক - 35, কোর 5, এক্সিকিউটার মেমরি - 9 জিবি


মামলা 3

উপরোক্ত পরিস্থিতিগুলি স্থির হিসাবে কয়েকটি সংখ্যক কোর গ্রহণ এবং এক্সিকিউটর এবং মেমরির # তে সরানো শুরু করে।

এখন প্রথম কেসটির জন্য, যদি আমরা মনে করি আমাদের 19 জিবি প্রয়োজন হয় না, এবং মাত্র 10 গিগাবাইটই যথেষ্ট, তবে নিম্নলিখিত সংখ্যাগুলি নিম্নরূপ:

প্রতিটি নোড = 3 এর জন্য নির্বাহকের 5 # টি কোরেস

এই পর্যায়ে, এটি আমাদের প্রথম গণনা অনুসারে 21, এবং তারপরে 19 এ নিয়ে যাবে। তবে যেহেতু আমরা ভেবেছিলাম 10 ঠিক আছে (সামান্য ওভারহেড ধরে নিই), তারপরে আমরা নোডের জন্য নির্বাহীদের # টি স্যুইচ করতে পারি না (63 63/১০ এর মতো)। নোডের জন্য exec জন এক্সিকিউটর এবং 5 কোরের সাথে উঠুন এটি নোডে 30 কোরে নেমে আসে, যখন আমাদের কেবল 16 কোর থাকে। সুতরাং আমাদের প্রতিটি নির্বাহকের জন্য কোডের সংখ্যাও পরিবর্তন করতে হবে।

সুতরাং আবার গণনা,

5 নম্বর ম্যাজিক 3 এ আসে (5 এর চেয়ে কম বা সমান যে কোনও সংখ্যা)। সুতরাং 3 টি কোর এবং 15 টি উপলব্ধ কোর সহ - আমরা নোডের জন্য 5 এক্সিকিউটার পেতে পারি। সুতরাং (5 * 6 -1) = 29 নির্বাহক

সুতরাং মেমরিটি 63/5 ~ 12. ওভার হেড 12 * .07 = .84 সুতরাং এক্সিকিউটারের মেমরি 12 - 1 জিবি = 11 জিবি

চূড়ান্ত নম্বরগুলি 29 এক্সিকিউটার, 3 কোর, এক্সিকিউটারের মেমরি 11 জিবি


গতিশীল বরাদ্দ:

দ্রষ্টব্য: গতিশীল বরাদ্দ সক্ষম করা থাকলে এক্সিকিউটারের সংখ্যার জন্য উপরের আবদ্ধ। সুতরাং এটি বলছে যে স্পার্ক অ্যাপ্লিকেশন প্রয়োজন হলে সমস্ত সংস্থান খেয়ে ফেলতে পারে। সুতরাং এমন একটি ক্লাস্টারে যেখানে আপনার অন্যান্য অ্যাপ্লিকেশন চলছে এবং তাদের কাজগুলি চালনার জন্যও কোরগুলির প্রয়োজন, দয়া করে নিশ্চিত হয়ে নিন যে আপনি এটি ক্লাস্টার পর্যায়ে করছেন। আমার অর্থ আপনি ব্যবহারকারীর অ্যাক্সেসের ভিত্তিতে YARN এর জন্য নির্দিষ্ট সংখ্যক কোর বরাদ্দ করতে পারেন। সুতরাং আপনি তৈরি করতে পারেন স্পার্ক_উজারটি হতে পারে এবং তারপরে সেই ব্যবহারকারীর জন্য কোর (মিনিট / সর্বোচ্চ) দিতে পারেন। এই সীমাগুলি স্পার্ক এবং অন্যান্য অ্যাপ্লিকেশনগুলির মধ্যে ভাগ করার জন্য যা ইয়ারনে চালিত হয়।

spark.dynamicAllocation.en सक्षम - এটি সত্য হিসাবে সেট করা হলে - আমাদের এক্সিকিউটারের উল্লেখ করার দরকার নেই। কারণটি নীচে:

স্টার্ক-জমা দেওয়ার সময় আমরা যে স্ট্যাটিক প্যারাম নম্বর দিই তা পুরো কাজের সময়কালের জন্য। তবে যদি গতিশীল বরাদ্দ চিত্রে আসে, তবে বিভিন্ন ধরণের ধরণ থাকবে

কি দিয়ে শুরু করবেন:

প্রারম্ভিক সংখ্যক এক্সিকিউটার ( স্পার্ক.ডিনামিকএলোকেশন ইনিটিয়াল এক্সেকিউটারস ) দিয়ে শুরু করতে

কতগুলো :

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

জিজ্ঞাসা বা দিতে কখন:

আমরা কখন নতুন এক্সিকিউটরদের ( স্পার্ক.ডিনামিকএলোকেশন.সচেডুলারব্যাকলগটাইমআউট ) অনুরোধ করব - এই অনেক সময়কালের জন্য এখানে प्रलंबित কাজ রয়েছে। অনুরোধ প্রতিটি রাউন্ডে অনুরোধ করা এক্সিকিউটারের সংখ্যা পূর্ববর্তী রাউন্ড থেকে তাত্ক্ষণিকভাবে বৃদ্ধি পায়। উদাহরণস্বরূপ, একটি অ্যাপ্লিকেশন প্রথম রাউন্ডে 1 জন নির্বাহক এবং তারপরে 2, 4, 8 এবং পরবর্তী রাউন্ডগুলিতে এক্সিকিউটারকে যুক্ত করবে। নির্দিষ্ট সময়ে, উপরের সর্বোচ্চটি ছবিতে আসে

কখন আমরা কোনও নির্বাহককে ছেড়ে দেব ( spark.dynamicAllocation.executorIdleTimeout ) -

আমি যদি কিছু মিস করি তবে দয়া করে আমাকে সংশোধন করুন। উপরোক্তগুলি আমি প্রশ্নে এবং কিছু অনলাইন সংস্থানগুলিতে ভাগ করে নেওয়া ব্লগের উপর ভিত্তি করে আমার বোঝাপড়া। ধন্যবাদ.

তথ্যসূত্র:


4
আমি কোথাও পড়েছি স্ট্যান্ড স্টোন মোডে নোডের জন্য কেবলমাত্র একজন নির্বাহক, সে সম্পর্কে কোনও ধারণা? আমি আপনার উত্তরে এটি আবৃত দেখতে পাচ্ছি না।
jangorecki

4
একটি স্বতন্ত্র ক্লাস্টারে, ডিফল্টরূপে আমরা প্রতি শ্রমিকের জন্য একজন নির্বাহী পাই। আমাদের spark.executor.cores এর সাথে খেলতে হবে এবং একজন শ্রমিকের একাধিক এক্সিকিউটর পেতে যথেষ্ট কোর রয়েছে।
রমজি

আমি খুঁজে পেয়েছি যে আমার কর্মী সেটআপ না করে সমস্ত 32 টি কোরের ব্যবহার করেছে spark.executor.cores, সুতরাং এটি ডিফল্টরূপে সমস্ত উপলব্ধ ব্যবহার করতে পারে।
jangorecki

হ্যাঁ, কোরগুলির জন্য ডিফল্টটি তারা যেমন বলে তেমনি অসীম। সুতরাং আপনি উল্লেখ না করলে স্পার্ক সমস্ত উপলব্ধ কোর ব্যবহার করতে পারে।
রমজি

4
@ র্যামজি আমি মনে করি এটি লক্ষ্য করা উচিত যে গতিশীল বরাদ্দ থাকা সত্ত্বেও, স্পার্ক যে বরাদ্দ করতে চলেছে তার প্রতিটি নির্বাহকের আকার নির্ধারণ করার জন্য আপনার এখনও স্পার্ক.এক্সিকিউটর কোডগুলি নির্দিষ্ট করা উচিত। অন্যথায়, যখনই স্পার্ক আপনার অ্যাপ্লিকেশনটিতে একটি নতুন এক্সিকিউটিউটর বরাদ্দ করতে চলেছে, এটি একটি সম্পূর্ণ নোড বরাদ্দ করতে চলেছে (যদি উপলভ্য থাকে) এমনকি আপনার যা প্রয়োজন কেবল আরও পাঁচটি কোর is
ড্যান মারখাসিন 21

6

এছাড়াও এটি আপনার ব্যবহারের ক্ষেত্রে নির্ভর করে, একটি গুরুত্বপূর্ণ কনফিগার প্যারামিটার হ'ল:

spark.memory.fractionথেকে - (300MB) মৃত্যুদন্ড এবং সঞ্চয় করার জন্য ব্যবহৃত (গাদা স্থান ভগ্নাংশ) http://spark.apache.org/docs/latest/configuration.html#memory-management

আপনি যদি ক্যাশে / অবিরত ব্যবহার না করেন তবে এটি 0.1 তে সেট করুন যাতে আপনার প্রোগ্রামের জন্য সমস্ত স্মৃতি থাকে।

আপনি যদি ক্যাশে / অব্যাহত ব্যবহার করেন, আপনি তোলা স্মৃতিটি পরীক্ষা করতে পারেন:

sc.getExecutorMemoryStatus.map(a => (a._2._1 - a._2._2)/(1024.0*1024*1024)).sum

আপনি কি এইচডিএফএস বা এইচটিটিপি থেকে ডেটা পড়েন?

আবার, আপনার ব্যবহারের ক্ষেত্রে একটি টিউনিং নির্ভর করে।


আপনি কি জানেন যে পাইপার্ক ব্যবহার করার সময় মানচিত্রের আদেশটি কেমন হবে? এক্সিকিউটার মেমরি স্ট্যাটাস () কে এক্সিকিউটারের স্ট্যাটাস পেতে আমি ব্যবহার করি, তবে যা ফিরে আসে তা দিয়ে কিছুই করতে পারি না ...
টমাস

4
দুঃখিত @ থমাস ডিকোক্স , তবে আপনি কি সেটিংটি বোঝাতে চাইছেন spark.memory.storageFraction=0.1? কারণ এএফআইএকি কার্যকর করা এবং স্টোরেজ উভয়ের জন্যই spark.memory.fractionব্যবহৃত মেমরির পরিমাণ নির্ধারণ করে (আপনি ইতিমধ্যে এটি উল্লেখ করেছেন) এবং কেবল মেমরির (যা স্টোরেজ + এক্সিকিউশন জন্য উপলব্ধ) ক্যাশে উচ্ছেদ থেকে সুরক্ষিত । দয়া করে এই লিঙ্কটি দেখুনSparkspark.memory.storageFraction
y2k-shubham

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