Distribution af eksekutorer, kerner og hukommelse til en Spark-applikation

ressourceallokering er et vigtigt aspekt under udførelsen af ethvert spark-job. Hvis det ikke er konfigureret korrekt, kan et spark-job forbruge hele klyngeressourcer og få andre applikationer til at sulte efter ressourcer

lad os starte med nogle grundlæggende definitioner af de udtryk, der bruges til håndtering af Spark-applikationer.

partitioner: en partition er en lille del af et stort distribueret datasæt. Spark administrerer data ved hjælp af partitioner, der hjælper med at parallelisere databehandling med minimal datablanding på tværs af eksekutorerne.

opgave: en opgave er en arbejdsenhed, der kan køres på en partition af et distribueret datasæt og udføres på en enkelt eksekutor. Enheden for parallel udførelse er på opgaveniveau.Alle opgaver med-i et enkelt trin kan udføres parallelt

eksekutor : en eksekutor er en enkelt JVM-proces, der lanceres til en applikation på en arbejdernode. Eksekutor kører opgaver og holder data i hukommelsen eller disklagring på tværs af dem. Hver ansøgning har sine egne eksekutorer. En enkelt node kan køre flere eksekutorer, og eksekutorer til en applikation kan spænde over flere arbejdernoder. En eksekutor forbliver op for
varigheden af Spark-applikationen og kører opgaverne i flere tråde. Antallet af eksekutorer til en spark-applikation kan specificeres inde i SparkConf eller via flag –num-eksekutorer fra kommandolinjen.

Cluster Manager : en ekstern tjeneste til erhvervelse af ressourcer på klyngen (f.eks. Spark er agnostisk for en klyngeleder, så længe den kan erhverve eksekutorprocesser, og de kan kommunikere med hinanden.Vi er primært interesseret i garn som cluster manager. En gnistklynge kan køre i enten garnklynge eller garnklienttilstand:

garnklienttilstand-en driver kører på klientproces, Application Master bruges kun til at anmode om ressourcer fra garn.

garn-cluster mode – en driver kører inde ansøgning master proces, klient går væk, når programmet er initialiseret

kerner : en kerne er en grundlæggende beregningsenhed CPU og en CPU kan have en eller flere kerner til at udføre opgaver på et givet tidspunkt. Jo flere kerner vi har, jo mere arbejde kan vi gøre. I spark styrer dette antallet af parallelle opgaver, som en eksekutor kan køre.

Distribution af eksekutorer, kerner og hukommelse til en Gnistapplikation, der kører i Garn:

spark-submit –class –num-eksekutorer ? – eksekutor-kerner ? – eksekutor-hukommelse ? ….

har du nogensinde spekuleret på, hvordan du konfigurerer –num-eksekutorer, –eksekutor-hukommelse og –bøddel-kerner spark config params til din klynge?

følgende liste indfanger nogle anbefalinger til at huske på, mens du konfigurerer dem:

  • Hadoop/Yarn / OS Deamons: når vi kører spark-applikation ved hjælp af en klyngemanager som garn, vil der være flere dæmoner, der kører i baggrunden som NameNode, sekundær NameNode, DataNode, JobTracker og TaskTracker. Så mens vi specificerer num-eksekutorer, skal vi sørge for, at vi forlader nok kerner (~1 kerne pr.
  • garn Ansøgningmaster (AM): ApplicationMaster er ansvarlig for at forhandle ressourcer fra ResourceManager og arbejde med NodeManagers for at udføre og overvåge containerne og deres ressourceforbrug. Hvis vi kører gnist på garn, så er vi nødt til at budgettere i de ressourcer, som AM ville have brug for (~1024MB og 1 eksekutor).
  • HDFS gennemløb: HDFS klient har problemer med tonsvis af samtidige tråde. Det blev observeret, at HDFS opnår fuld skrive gennemløb med ~5 opgaver pr eksekutor . Så det er godt at holde antallet af kerner pr.
  • MemoryOverhead: Følgende billede viser spark-garn-memory-usage.
billede

to ting at notere fra dette billede:

1
2
3
4
5

Full memory requested to yarn per executor =
spark-executor-memory + spark.yarn.executor.memoryOverhead.
spark.yarn.executor.memoryOverhead =
Max(384MB, 7% of spark.eksekutor-hukommelse)

så hvis vi anmoder om 20 GB pr.eksekutor, får AM faktisk 20 GB + memoryOverhead = 20 + 7% af 20 GB = ~23 GB hukommelse til os.

  • kørsel af eksekutorer med for meget hukommelse resulterer ofte i for store forsinkelser i affaldsindsamling.
  • kørsel af små eksekutorer (med en enkelt kerne og lige nok hukommelse, der er nødvendig for at køre en enkelt opgave, for eksempel) smider de fordele, der kommer fra at køre flere opgaver i en enkelt JVM.

der er to måder, hvorpå vi konfigurerer eksekutoren og kernedetaljerne til Gnistjobbet. De er:

  1. statisk allokering – værdierne er angivet som en del af spark-submit
  2. dynamisk allokering – værdierne afhentes baseret på kravet (datastørrelse, nødvendige beregninger) og frigives efter brug. Dette hjælper ressourcerne til at blive genbrugt til andre applikationer.

statisk tildeling:

lad os nu overveje en 10 node klynge med følgende config og analysere forskellige muligheder for eksekutorer-core-memory distribution:

1
2
3
4

**Cluster Config:**
10 Nodes
16 cores per Node
64GB RAM per Node

First Approach: Tiny executors :

Tiny executors essentially means one executor per core. Følgende tabel viser værdierne for vores spar-config params med denne tilgang:

1
2
3
4
5
6
7
8
9

–num-executors = In this approach, we’ll assign one executor per core
= total-cores-in-cluster
= num-cores-per-node * total-nodes-in-cluster
= 16 x 10 = 160
–eksekutor-kerner = 1 (en eksekutor pr. kerne)
–eksekutor-hukommelse = mængde hukommelse pr.eksekutor
= mem-per-node/num-eksekutorer-per-node
= 64GB/16 = 4GB

erne, som vi diskuterede ovenfor, kan vi ikke drage fordel af at køre flere opgaver i samme JVM. Delte / cachelagrede variabler som udsendelsesvariabler og akkumulatorer replikeres også i hver kerne af knudepunkterne, som er 16 gange. Også, vi ikke forlader nok hukommelse overhead for Hadoop / garn dæmon processer, og vi tæller ikke i ApplicationManager. IKKE GODT!

anden tilgang: Fat eksekutorer (en eksekutor pr.node):

Fat eksekutorer betyder i det væsentlige en eksekutor pr. node. Følgende tabel viser værdierne for vores spark-config params med denne tilgang:

1
2
3
4
5
6
7
8
9
10

–num-executors = In this approach, we’ll assign one executor per node
= total-nodes-in-cluster
= 10
–executor-cores = one executor per node means all kernerne i noden er tildelt en eksekutor
= total-cores-in-a-node
= 16
–eksekutor-hukommelse = mængde hukommelse pr.eksekutor
= mem-per-node/num-eksekutorer-per-node
= 64GB/1 = 64GB

analyse: med alle 16 kerner pr. Også, ikke godt!

tredje tilgang: Balance mellem fedt (vs) lille

ifølge de anbefalinger, som vi diskuterede ovenfor:

  • Based on the recommendations mentioned above, Let’s assign 5 core per executors =>--executor-cores = 5 (for good HDFS throughput)
  • Leave 1 core per node for Hadoop/Yarn daemons => Num cores available per node = 16-1 = 15
  • So, Total available of cores in cluster = 15 x 10 = 150
  • Number of available executors = (total cores/num-cores-per-executor) = 150/5 = 30
  • Leaving 1 executor for ApplicationManager =>--num-executors = 29
  • Number of executors per node = 30/10 = 3
  • Memory per executor = 64GB/3 = 21GB
  • tælling af heap overhead = 7% af 21GB = 3GB. Så faktisk --executor-memory = 21 – 3 = 18GB

så anbefalet config er: 29 eksekutorer, 18GB hukommelse hver og 5 kerner hver!!

Analyse: Det er indlysende, hvordan denne tredje tilgang har fundet den rette balance mellem fedt vs små tilgange. Det er overflødigt at sige, at det opnåede parallelisme af en fed eksekutor og bedst gennemløb af en lille eksekutor!!

dynamisk allokering

Bemærk: øvre grænse for antallet af eksekutorer, hvis dynamisk allokering er aktiveret, er uendelig. Så dette siger, at spark-applikationen kan spise alle ressourcerne væk, hvis det er nødvendigt. I en klynge, hvor vi har andre applikationer kørende, og de også har brug for kerner til at køre opgaverne, skal vi sørge for, at vi tildeler kernerne på klyngeniveau.

dette betyder, at vi kan allokere specifikt antal kerner til GARNBASEREDE applikationer baseret på brugeradgang. Så vi kan oprette en spark_user og derefter give kerner (min/Maks) til den bruger. Disse grænser er for deling mellem spark og andre applikationer, der kører på garn.

for at forstå dynamisk allokering skal vi have kendskab til følgende egenskaber:

spark.dynamicAllocation.aktiveret – når dette er indstillet til sandt, behøver vi ikke nævne eksekutorer. Årsagen er nedenfor:

de statiske parameternumre, vi giver hos spark-submit, er for hele jobvarigheden. Men hvis dynamisk allokering kommer ind i billedet, ville der være forskellige faser som følgende:

Hvad er antallet for eksekutorer til at starte med:

indledende antal eksekutorer (spark.dynamicAllocation.start med

styring af antallet af eksekutorer dynamisk:

derefter baseret på belastning (afventende opgaver), hvor mange eksekutorer der skal anmodes om. Dette ville i sidste ende være det nummer, hvad vi giver ved spark-submit på statisk måde. Så når de oprindelige eksekutornumre er indstillet, går vi til min (spark.dynamicAllocation.mineksekutorer) og maks (gnist.dynamicAllocation.tal.

Hvornår skal man spørge nye eksekutorer eller give væk nuværende eksekutorer:

hvornår anmoder vi om nye eksekutorer (spark.dynamicAllocation.schedulerBacklogTimeout) – det betyder, at der har været afventende opgaver for denne meget varighed. Så anmodningen om antallet af eksekutorer, der anmodes om i hver runde, stiger eksponentielt fra den foregående runde. For eksempel vil en ansøgning tilføje 1 eksekutor i første runde og derefter 2, 4, 8 og så videre eksekutorer i de efterfølgende runder. På et bestemt tidspunkt kommer ovenstående egenskabsmaksimum ind i billedet.

Hvornår giver vi væk en eksekutor indstilles ved hjælp af spark.dynamicAllocation.eksekutoridletimeout.

for at konkludere, hvis vi har brug for mere kontrol over jobudførelsestiden, skal du overvåge jobbet for uventet datavolumen, de statiske tal vil hjælpe. Ved at flytte til dynamisk vil ressourcerne blive brugt i baggrunden, og de job, der involverer uventede mængder, kan påvirke andre applikationer.

https://stackoverflow.com/questions/24622108/apache-spark-the-number-of-cores-vs-the-number-of-executors
http://spark.apache.org/docs/latest/configuration.html#dynamic-allocation
http://spark.apache.org/docs/latest/job-scheduling.html#resource-allocation-policy
https://blog.cloudera.com/blog/2015/03/how-to-tune-your-apache-spark-jobs-part-2/
http://spark.apache.org/docs/latest/cluster-overview.html

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.