[hadoop] Apache Spark : 코어 수와 실행기 수

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 전력을 사용할 수 있습니다. 따라서 스레드 수의 문제가 아닐 수 있습니다.

이 결과를 설명하는 방법?



답변

이 모든 것을 좀 더 구체적으로 만들기 위해 가능한 한 많은 클러스터를 사용하도록 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 부) 기사에 설명되어 있습니다.


답변

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

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

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


답변

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

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


답변

짧은 대답 : 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가 한 번에 하나 이상의 작업을 수행하도록함으로써 대기 시간과 작업 시간이 줄어들고 성능이 향상됩니다.


답변

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

스파크 정의 :

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

노드 : 서버

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

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

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

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

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


답변

Spark 동적 할당은 유연성을 제공하고 리소스를 동적으로 할당합니다. 이 수에서 최소 및 최대 실행자를 제공 할 수 있습니다. 또한 응용 프로그램을 시작할 때 시작해야하는 실행 프로그램 수도 제공 할 수 있습니다.

아래에서 동일하게 읽으십시오.

http://spark.apache.org/docs/latest/configuration.html#dynamic-allocation


답변

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

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

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

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