Apache Spark : 코어 수와 실행기 수


194

YARN에서 Spark 작업을 실행할 때 코어 수와 실행기 수의 관계를 이해하려고합니다.

테스트 환경은 다음과 같습니다.

  • 데이터 노드 수 : 3
  • 데이터 노드 머신 사양 :
    • CPU : 코어 i7-4790 (코어 수 : 4, 스레드 수 : 8)
    • RAM : 32GB (8GB x 4)
    • HDD : 8TB (2TB x 4)
  • 네트워크 : 1Gb

  • 스파크 버전 : 1.0.0

  • 하둡 버전 : 2.4.0 (Hortonworks HDP 2.1)

  • Spark 작업 흐름 : sc.textFile-> 필터-> 맵-> 필터-> mapToPair-> reduceByKey-> 맵-> saveAsTextFile

  • 입력 데이터

    • 유형 : 단일 텍스트 파일
    • 크기 : 165GB
    • 라인 수 : 454,568,833
  • 산출

    • 두 번째 필터 이후 줄 수 : 310,640,717
    • 결과 파일의 라인 수 : 99,848,268
    • 결과 파일 크기 : 41GB

작업은 다음 구성으로 실행되었습니다.

  1. --master yarn-client --executor-memory 19G --executor-cores 7 --num-executors 3 (데이터 노드 당 실행기, 코어만큼 사용)

  2. --master yarn-client --executor-memory 19G --executor-cores 4 --num-executors 3 (코어 수 감소)

  3. --master yarn-client --executor-memory 4G --executor-cores 2 --num-executors 12 (핵심이 적고 집행자가 많음)

경과 시간 :

  1. 50 분 15 초

  2. 55 분 48 초

  3. 31 분 23 초

놀랍게도 (3)이 훨씬 빨랐습니다.
나는 섞을 때 집행 간 의사 소통이 적기 때문에 (1)이 더 빠를 것이라고 생각했다.
(1)의 코어 수는 (3)보다 적지 만 2)가 제대로 수행되었으므로 코어 수는 핵심 요소가 아닙니다.

(pwilmot의 답변 후에 다음이 추가되었습니다.)

정보의 성능 모니터 화면 캡처는 다음과 같습니다.

  • (1)에 대한 Ganglia 데이터 노드 요약-작업은 04:37에 시작되었습니다.

(1)에 대한 Ganglia 데이터 노드 요약

  • (3)에 대한 Ganglia 데이터 노드 요약-작업은 19:47에 시작되었습니다. 그 시간 전에 그래프를 무시하십시오.

(3)에 대한 Ganglia 데이터 노드 요약

그래프는 크게 두 섹션으로 나뉩니다.

  • 첫째 : 시작부터 축소까지 : ByKey : CPU 집약적이며 네트워크 활동이 없음
  • 둘째 : reduceByKey 후 : CPU가 낮아지면 네트워크 I / O가 수행됩니다.

그래프에서 볼 수 있듯이 (1)은 주어진만큼의 CPU 전력을 사용할 수 있습니다. 따라서 스레드 수의 문제가 아닐 수 있습니다.

이 결과를 설명하는 방법?


2
이제 GC가 의심됩니다. 사실 Spark UI에서 GC에 소요되는 총 시간은 1) 2)보다 더 깁니다.
zeodtr

왜 19G로 3)을 시도하지 않았습니까? 작업자를 4G로 제한하면 일부 ppl이 발견 한 NUMA 효과가 감소 할 수 있습니까? 즉, 4G는 워크 플로에 할당 된 2 개의 코어 중 하나에 있으므로 I / O 속도 저하가 적어 전반적인 성능이 향상됩니다. 그렇지 않으면 주된 질문은 작업자에 대해 하나의 단일 실행기를 사용할 수있는 코어 / 스레드 수는 몇 개인가? (실행자의 세분성이 아닌 작업자의 총 코어 수만 지정할 수 있음)
Bacon

5
Btw 방금 core / src / main / scala / org / apache / spark / deploy / worker / ExecutorRunner.scala에서 코드를 확인했는데 1 executor = 1 worker thread입니다.
베이컨

약간 늦었지만 여기에이 주제에 대한 cloudera 관련 게시물이 있습니다. blog.cloudera.com/blog/2015/03/…
Orelus

1
그런데, 나는 클라우 데라 슬라이드 갑판에서이 정보를 찾을 slideshare.net/cloudera/... decission의 집행, 코어의 결정 및 메모리에 대한 약간의 설명,
마니 Sahni

답변:


58

이 모든 것을 좀 더 구체적으로 만들기 위해 가능한 한 많은 클러스터를 사용하도록 Spark 앱을 구성하는 효과적인 예가 있습니다. 각각 16 개의 코어와 64GB의 메모리가 장착 된 NodeManager를 실행 하는 6 개의 노드가 있는 클러스터를 상상해보십시오 . NodeManager 용량, yarn.nodemanager.resource.memory-mb 및 yarn.nodemanager.resource.cpu-vcores는 각각 63 * 1024 = 64512 (메가 바이트) 및 15로 설정해야합니다. 노드는 OS 및 Hadoop 데몬을 실행하기 위해 약간의 리소스가 필요하기 때문에 리소스의 100 %를 YARN 컨테이너에 할당하지 마십시오. 이 경우 이러한 시스템 프로세스에 기가 바이트와 코어를 남겨 둡니다. Cloudera Manager는이를 설명하고 이러한 YARN 속성을 자동으로 구성하여 도움을줍니다.

아마도 첫 번째 충동은 --num-executors 6 --executor-cores 15 --executor-memory 63G를 사용하는 것 입니다. 그러나 이것은 다음과 같은 이유로 잘못된 접근 방식입니다.

63GB + 실행기 메모리 오버 헤드는 NodeManager의 63GB 용량에 맞지 않습니다. 응용 프로그램 마스터는 노드 중 하나에서 코어를 사용하므로 해당 노드에 15 코어 실행기를위한 공간이 없습니다. 실행기 당 15 개의 코어는 잘못된 HDFS I / O 처리량으로 이어질 수 있습니다.

더 나은 옵션은 --num-executors 17 --executor-cores 5 --executor-memory 19G를 사용하는 것 입니다. 왜?

이 구성으로 인해 AM이있는 노드를 제외한 모든 노드에 세 개의 실행자가 있으며 두 개의 실행기가 있습니다. -실행자-메모리는 (노드 당 63/3 실행자) = 21. 21 * 0.07 = 1.47로 도출되었습니다. 21 – 1.47 ~ 19.

Cloudera의 블로그 인 How-to : Apache Spark 작업 조정 (2 부) 기사에 설명되어 있습니다.


1
"이 구성은 AM이있는 노드를 제외한 모든 노드에서 3 개의 실행자가 있으며, 두 개의 실행기가 있습니다.". "--executor-cores 5"와 관련하여 이것은 무엇을 의미합니까?
derek

각 실행자가 5 개의 코어를 사용한다는 의미입니다. 각 노드에는 15 개의 코어를 사용하는 3 개의 실행 프로그램이 있으며, 노드 중 하나가 작업에 대한 응용 프로그램 마스터를 실행하는 것 외에는 2 개의 실행 프로그램, 즉 10 개의 코어 만 실행자로 호스트 할 수 있습니다.
Davos

잘 설명되어 있습니다-이것이 yarn.scheduler.capacity.resource-calculator기본값 인 disabled에 적용됩니다 . 기본적으로 CPU가 아닌 메모리별로 예약되기 때문입니다.
YoYo

1
더 많은 실행자가 HDFS I / O 처리량을 저하시킬 수 있습니다. 따라서 HDFS를 전혀 사용하지 않으면 실행기 당 5 개 이상의 코어를 사용할 수 있습니까?
Darshan

Application Master는 각 노드에서 실행됩니다. 위와 같이 이는 작업을 실행하기 위해 단 하나의 응용 프로그램 마스터 만 있음을 의미합니다. 그 맞습니까?
로샨 페르난도

15

Sandy Ryza 에 따르면 스파크 앱을 HDFS 위에서 실행하면

HDFS 클라이언트가 수많은 동시 스레드에 문제가 있음을 알았습니다. 대략 executor 당 최대 5 개의 태스크가 전체 쓰기 처리량을 달성 할 수 있으므로 executor 당 코어 수를 해당 수 아래로 유지하는 것이 좋습니다.

따라서 첫 번째 구성이 세 번째 구성보다 느리다고 생각합니다. HDFS I / O 처리량이 나쁘기 때문입니다.


11

나는이 설정을 직접 연주하지 않았으므로 이것은 단지 추측 일이지만 분산 시스템 에서이 문제를 일반 코어 및 스레드로 생각하면 클러스터에서 최대 12 코어 (4 * 3 시스템) 및 24 스레드를 사용할 수 있습니다 (8 * 3 기계). 처음 두 예제에서는 작업에 상당한 수의 코어 (잠재적 계산 공간)를 제공하지만 해당 코어에서 실행할 스레드 (작업) 수는 너무 제한되어 할당 된 처리 능력을 많이 사용할 수 없습니다 따라서 더 많은 계산 리소스가 할당되어 있어도 작업 속도가 느려집니다.

문제는 셔플 단계에 있다고 언급했습니다. 셔플 단계에서 오버 헤드를 제한하는 것이 좋지만 일반적으로 클러스터의 병렬화를 사용하는 것이 훨씬 더 중요합니다. 셔플이없는 단일 스레드 프로그램 인 극단적 인 경우를 생각해보십시오.


답변 주셔서 감사합니다. 그러나 스레드 수는 주요 문제가 아니라고 생각합니다. 모니터링 화면 캡처를 추가했습니다. 그래프에서 볼 수 있듯이 1) 주어진만큼의 CPU 전력을 사용할 수 있습니다.
zeodtr

1
@zeodtr pwilmot가 정확합니다. 코어의 잠재력을 최대한 활용하려면 최소 2-4 개의 작업이 필요합니다. 나는 이것을 80 코어 클러스터에 최소한 1000 개의 파티션을 사용한다.
samthebest

@samthebest 내가 알고 싶은 것은 1)과 3)의 성능 차이의 이유입니다. Spark UI를 볼 때 섹션 2에서 21 개의 작업을 병렬로 실행합니다 (3의 경우 24 대신 21 인 이유는 알 수 없음). 그러나 3)의 작업은 더 빨리 실행됩니다.
zeodtr

10

짧은 대답 : tgbaggio 가 옳다고 생각 합니다. 실행기에서 HDFS 처리량 한계에 도달했습니다.

나는 여기에 대한 대답이 여기의 일부 권장 사항보다 약간 간단하다고 생각합니다.

나를위한 단서는 클러스터 네트워크 그래프에 있습니다. 실행 1의 경우 사용률은 ~ 50M bytes / s로 안정적입니다. 3을 실행하면 꾸준한 사용률이 약 100M 바이트 / 초로 두 배가됩니다.

에서 클라우 데라의 블로그 게시물 을 공유 DzOrd ,이 중요한 견적을 볼 수 있습니다 :

HDFS 클라이언트가 수많은 동시 스레드에 문제가 있음을 알았습니다. 대략적인 추측은 실행기 당 최대 5 개의 작업이 전체 쓰기 처리량을 달성 할 수 있으므로 실행기 당 코어 수를 해당 수 미만으로 유지하는 것이 좋습니다.

따라서 몇 가지 계산을 수행하여 그것이 사실이라면 어떤 성능을 기대하는지 봅시다.


실행 1 : 19GB, 코어 7 개, 실행기 3 개

  • 3 개의 실행기 x 7 스레드 = 21 스레드
  • 실행기 당 7 개의 코어를 사용하면 IO를 HDFS로 제한 할 것으로 예상됩니다 (최대 5 코어에서 최대)
  • 유효 처리량 ~ = 3 개의 실행기 x 5 개의 스레드 = 15 개의 스레드

실행 3 : 4GB, 2 코어, 12 개의 실행기

  • 2 개의 실행기 x 12 스레드 = 24 스레드
  • 실행기 당 2 개의 코어가 있으므로 hdfs 처리량은 정상입니다
  • 유효 처리량 ~ = 12 개의 실행기 x 2 개의 스레드 = 24 개의 스레드

작업이 동시성 (스레드 수)에 의해 100 % 제한되는 경우 우리는 런타임이 스레드 수와 완전히 역으로 상관 될 것으로 기대합니다.

ratio_num_threads = nthread_job1 / nthread_job3 = 15/24 = 0.625
inv_ratio_runtime = 1/(duration_job1 / duration_job3) = 1/(50/31) = 31/50 = 0.62

따라서 ratio_num_threads ~= inv_ratio_runtime네트워크 제한이있는 것 같습니다.

이 효과는 실행 1과 실행 2의 차이점을 설명합니다.


실행 2 : 19GB, 코어 4 개, 실행기 3 개

  • 3 개의 실행기 x 4 개의 스레드 = 12 개의 스레드
  • 실행기 당 4 개의 코어, 괜찮은 IO to HDFS
  • 유효 처리량 ~ = 3 개의 실행기 x 4 개의 스레드 = 12 개의 스레드

유효 스레드 수와 런타임 비교

ratio_num_threads = nthread_job2 / nthread_job1 = 12/15 = 0.8
inv_ratio_runtime = 1/(duration_job2 / duration_job1) = 1/(55/50) = 50/55 = 0.91

마지막 비교만큼 완벽하지는 않지만 스레드를 잃어도 비슷한 성능 저하를 볼 수 있습니다.

마지막 비트 : 더 많은 스레드, 예를 들어 더 나은 성능을 얻는 이유는 무엇입니까? CPU 수보다 많은 스레드?

Rob Pike의 병행 성 (병렬 처리 (데이터를 여러 CPU로 분할하여 얻은 것)과 동시성 (여러 스레드를 사용하여 단일 CPU에서 작업 할 때 얻는 것)의 차이점에 대한 설명은 Rob Pike : Concurrency에서 제공합니다. 병렬 처리가 아닙니다 .

간단한 설명은 Spark 작업이 파일 시스템 또는 네트워크와 상호 작용하는 경우 CPU가 해당 인터페이스와의 통신을 기다리는 데 많은 시간을 소비하고 실제로 "작업을 수행"하는 데 많은 시간을 소비하지 않는다는 것입니다. CPU가 한 번에 하나 이상의 작업을 수행하도록함으로써 대기 시간과 작업 시간이 줄어들고 성능이 향상됩니다.


1
흥미롭고 설득력있는 설명으로, 실행자가 최대 처리량을 달성하기 위해 5 개의 작업 제한 이 있다는 추측을 어떻게했는지 궁금합니다 .
Dat Nguyen

숫자 5는 내가 생각해 낸 것이 아닙니다. IO 병목 현상의 징후를 발견하고 병목 현상이 발생할 수있는 곳을 찾기 위해 출발했습니다.
turtlemonvh

8

로부터 우수한 에서 사용 가능한 자원 RStudio의 Sparklyr 패키지 페이지 :

스파크 정의 :

Spark 명명법에 대한 몇 가지 간단한 정의를 제공하는 것이 유용 할 수 있습니다.

노드 : 서버

작업자 노드 : 클러스터의 일부이며 Spark 작업을 실행할 수있는 서버

마스터 노드 : 작업자 노드를 조정하는 서버.

Executor : 노드 내부의 일종의 가상 머신. 하나의 노드에는 여러 실행자가있을 수 있습니다.

Driver Node : Spark 세션을 시작하는 노드입니다. 일반적으로이 서버는 sparklyr가있는 서버입니다.

드라이버 (실행자) : 드라이버 노드도 실행자 목록에 나타납니다.



1

내가 생각하는 처음 두 가지 구성에는 작은 문제가 있습니다. 스레드와 코어의 개념은 다음과 같습니다. 스레딩의 개념은 코어가 이상적인 경우 해당 코어를 사용하여 데이터를 처리하는 것입니다. 따라서 처음 두 경우에는 메모리가 완전히 활용되지 않습니다. 이 예제를 벤치마킹하려면 각 머신에 코어10 개 이상있는 머신을 선택하십시오 . 그런 다음 벤치 마크를 수행하십시오.

그러나 실행기 당 5 개 이상의 코어를 제공하지 마십시오. I / O 성능에 병목 현상이 발생합니다.

따라서이 벤치 마킹을 수행하는 가장 좋은 기계는 코어가 10 개인 데이터 노드 일 수 있습니다.

데이터 노드 시스템 사양 : CPU : Core i7-4790 (코어 수 : 10, 스레드 수 : 20) RAM : 32GB (8GB x 4) HDD : 8TB (2TB x 4)


0

가장 큰 이유 중 하나는 지역성이라고 생각합니다. 입력 파일 크기는 165G이며 파일의 관련 블록이 여러 DataNode에 확실히 분산되어 있으므로 더 많은 실행자가 네트워크 복사를 피할 수 있습니다.

실행기 수를 동일한 블록 수로 설정하십시오. 더 빠를 수 있다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.