스파크 실행기 번호, 코어 및 실행기 메모리를 조정하는 방법은 무엇입니까?


84

위에서 언급 한 매개 변수를 어디에서 조정하기 시작합니까? 실행기 메모리로 시작하여 실행기 수를 얻거나 코어로 시작하여 실행기 번호를 얻습니까? 나는 링크를 따랐다 . 그러나 높은 수준의 아이디어를 얻었지만 어떻게 시작하고 최종 결론에 도달해야할지 아직 확실하지 않습니다.

답변:


206

다음 답변은 제목에 언급 된 세 가지 주요 측면 (실행기 수, 실행기 메모리 및 코어 수)을 다룹니다. 이 답변에서 다루지 않았지만 가까운 장래에 추가하고 싶은 드라이버 메모리 및 기타 매개 변수와 같은 다른 매개 변수가있을 수 있습니다.

사례 1 하드웨어-6 개 노드, 각 노드 16 개 코어, 64GB RAM

각 실행기는 JVM 인스턴스입니다. 따라서 단일 노드에 여러 실행기를 가질 수 있습니다.

OS 및 Hadoop 데몬에는 처음 1 개 코어와 1GB가 필요하므로 각 노드에 대해 15 개 코어, 63GB RAM을 사용할 수 있습니다.

코어 수를 선택하는 방법부터 시작하십시오 .

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, 실행자 메모리-19GB


케이스 2 하드웨어 : 동일 6 노드, 32 코어, 64GB

5는 좋은 동시성을 위해 동일합니다.

각 노드의 실행기 수 = 32/5 ~ 6

따라서 총 실행자 = 6 * 6 노드 = 36. 그러면 최종 수는 AM = 35 일 때 36-1입니다.

실행기 메모리는 각 노드에 대해 6 개의 실행기입니다. 63/6 ~ 10. 오버 헤드는 .07 * 10 = 700MB입니다. 따라서 머리 위로 1GB로 반올림하면 10-1 = 9GB가됩니다.

최종 번호-실행자-35, 코어 5, 실행자 메모리-9GB


사례 3

위의 시나리오는 코어 수를 고정 된 것으로 받아들이고 실행기 및 메모리 수로 이동하는 것으로 시작합니다.

이제 첫 번째 경우 19GB가 필요하지 않고 10GB만으로 충분하다고 생각하면 다음과 같은 숫자가 있습니다.

코어 5 각 노드에 대한 실행기 수 = 3

이 단계에서 이것은 첫 번째 계산에 따라 21과 19로 이어질 것입니다. 그러나 우리는 10이 괜찮다고 생각했기 때문에 (약간 오버 헤드를 가정), 노드 당 실행기 수를 6 (63/10과 같이)으로 전환 할 수 없습니다. 노드 당 실행기가 6 개이고 코어가 5 개인 경우 코어가 16 개 뿐인 경우 노드 당 30 개 코어로 줄어 듭니다. 따라서 각 실행기의 코어 수도 변경해야합니다.

다시 계산하면

매직 넘버 5는 3이됩니다 (5보다 작거나 같은 숫자). 따라서 3 개의 코어와 15 개의 사용 가능한 코어로 노드 당 5 개의 실행기를 얻습니다. 따라서 (5 * 6 -1) = 29 명의 집행자

따라서 메모리는 63/5 ~ 12입니다. 오버 헤드는 12 * .07 = .84이므로 실행기 메모리는 12-1GB = 11GB입니다.

최종 숫자는 29 개의 실행기, 3 개의 코어, 실행기 메모리는 11GB입니다.


동적 할당 :

참고 : 동적 할당이 활성화 된 경우 실행기 수의 상한입니다. 따라서 이것은 스파크 애플리케이션이 필요한 경우 모든 리소스를 먹을 수 있음을 의미합니다. 따라서 다른 응용 프로그램이 실행 중이고 작업을 실행하기 위해 코어가 필요한 클러스터에서는 클러스터 수준에서 수행해야합니다. 사용자 액세스를 기반으로 YARN에 특정 수의 코어를 할당 할 수 있습니다. 따라서 spark_user를 만든 다음 해당 사용자에 대한 코어 (최소 / 최대)를 제공 할 수 있습니다. 이러한 제한은 Spark와 YARN에서 실행되는 다른 애플리케이션 간의 공유를위한 것입니다.

spark.dynamicAllocation.enabled-이것이 true로 설정된 경우-실행자를 언급 할 필요가 없습니다. 그 이유는 다음과 같습니다.

spark-submit에서 제공하는 정적 매개 변수 번호는 전체 작업 기간 동안입니다. 그러나 동적 할당이 그림에 나타나면 다음과 같은 다른 단계가있을 것입니다.

무엇으로 시작해야할까요?

시작할 초기 실행기 수 ( spark.dynamicAllocation.initialExecutors )

얼마나 :

그런 다음로드 (보류중인 작업)에 따라 얼마나 많은 것을 요청할 수 있는지. 이것은 결국 우리가 정적 인 방식으로 spark-submit에서주는 숫자가 될 것입니다. 따라서 초기 실행기 번호가 설정되면 최소 ( spark.dynamicAllocation.minExecutors ) 및 최대 ( spark.dynamicAllocation.maxExecutors ) 번호로 이동합니다.

요청 또는 제공시기 :

새 실행기를 언제 요청합니까 ( spark.dynamicAllocation.schedulerBacklogTimeout )-이 기간 동안 보류중인 작업이있었습니다. 그래서 요청하십시오. 각 라운드에서 요청 된 집행자 수는 이전 라운드에서 기하 급수적으로 증가합니다. 예를 들어, 응용 프로그램은 첫 번째 라운드에서 실행자를 1 명 추가 한 다음 후속 라운드에서 실행자를 2, 4, 8 등으로 추가합니다. 특정 지점에서 위의 최대 값이 그림에 나타납니다.

언제 우리는 실행자를 포기합니까 ( spark.dynamicAllocation.executorIdleTimeout )-

내가 놓친 것이 있으면 정정하십시오. 위의 내용은 내가 질문 한 블로그와 일부 온라인 리소스를 기반으로 이해 한 것입니다. 감사합니다.

참조 :


2
독립형 모드에서 노드 당 실행기가 하나만있는 곳에서 읽었습니다. 귀하의 답변에서 다루지 않은 것 같습니다.
jangorecki

2
독립형 클러스터에서는 기본적으로 작업 자당 하나의 실행기를 얻습니다. 우리는 spark.executor.cores를 가지고 놀아야하고 작업자는 둘 이상의 실행자를 얻기에 충분한 코어를 가지고 있습니다.
Ramzy

내 작업자는을 설정하지 않고 32 개 코어를 spark.executor.cores모두 사용하므로 기본적으로 사용 가능한 모든 코어를 사용할 수 있습니다.
jangorecki

예, 코어의 기본값은 그들이 말하는 것처럼 무한합니다. 따라서 Spark는 지정하지 않는 한 사용 가능한 모든 코어를 사용할 수 있습니다.
Ramzy

2
@Ramzy 동적 할당을 사용하더라도 Spark가 할당 할 각 실행기의 크기를 결정하려면 spark.executor.cores를 지정해야합니다. 그렇지 않으면 Spark가 애플리케이션에 새 실행기를 할당 할 때마다 필요한 모든 코어가 5 개만 더 있더라도 전체 노드 (사용 가능한 경우)를 할당합니다.
Dan Markhasin

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

HDFS 또는 HTTP에서 데이터를 읽습니까?

다시 말하지만 튜닝은 사용 사례에 따라 다릅니다.


pyspark를 사용할 때 map 명령이 어떻게 생겼는지 알고 있습니까? . 나는 getExecutorMemoryStatus ()가 실행 프로그램의 상태를 얻을 수 sc._jsc.sc ()를 사용하지만 반환 것과 아무것도 할 수 없어 ...
토마스

1
@Thomas Decaux 미안 하지만 설정을 의미 spark.memory.storageFraction=0.1했습니까? AFAIK spark.memory.fraction실행 및 저장 (이미 언급 했음) Spark모두에 사용되는 메모리 양을 결정하고 메모리 (저장 + 실행에 사용할 수 있음) 만 캐시 제거에서 제외 됩니다 . 이 링크를 참조하십시오spark.memory.storageFraction
y2k-shubham

@Thomas 내 응용 프로그램에서이 옵션도 적용 할 수있는 것보다 persist (StorageLevel.DISK_ONLY) 만 있으면 맞습니까? 메모리 부분에만 영향을 주지만 디스크 유출에는 영향을주지 않습니까?
jk1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.