GNU make : 작업 수가 시스템의 CPU 코어 수와 같아야합니까?


87

GNU make의 작업 수가 코어 수와 같아야하는지 아니면 대기열에 추가 할 수있는 작업 하나를 추가하여 빌드 시간을 최적화 할 수 있는지, 다른 작업은 "작동"하는지에 대한 논란이있는 것 같습니다. .

더 나은 사용하는 것 -j4또는 -j5쿼드 코어 시스템에?

둘 중 하나를 지원하는 벤치마킹을 보거나 수행 했습니까?


8
make `nproc`을 위해 CPU 독립 스크립트를 만드는 데 사용할 수 있습니다. :)
VivienG

io 바인딩과 CPU 바인딩 된 레시피가 혼합되어있는 경우 잠재적으로 NCPU보다 더 많은 것을 원할 것입니다. -lX 옵션 추가도 고려하십시오. 이것은 "하드웨어에 따라 작업을 수행"하는 것 외에는 답할 수있는 질문이 아닙니다.
제임스 무어

기술적으로 개선을 볼 수 있습니다. 느린 디스크, 충분한 램 및 많은 작은 소스 코드 파일이 필요합니다. 10 년 전에는 더 쉽게 올 수 있습니다.
Hans Passant

답변:


56

가장 좋은 방법은 특정 환경과 워크로드에서 직접 벤치마킹하는 것입니다. 하나의 크기로 모든 답변을하기에는 너무 많은 변수 (소스 파일의 크기 / 수, 사용 가능한 메모리, 디스크 캐싱, 소스 디렉토리 및 시스템 헤더가 다른 디스크에 있는지 여부 등)가있는 것 같습니다.

내 개인적인 경험 (2 코어 MacBook Pro에서)은 -j2가 -j1보다 훨씬 빠르지 만 그 이상 (-j3, -j4 등)은 측정 가능한 속도 향상이 없다는 것입니다. 따라서 내 환경에서는 "작업 == 코어 수"가 좋은 대답 인 것 같습니다. (YMMV)


57

하이퍼 스레딩 랩톱을 사용하여 4 코어에서 홈 프로젝트를 실행하고 결과를 기록했습니다. 이것은 상당히 컴파일러가 많은 프로젝트이지만 마지막에 17.7 초의 단위 테스트를 포함합니다. 컴파일은 IO 집약적이지 않습니다. 사용 가능한 메모리가 매우 많으며 나머지는 빠른 SSD에 있습니다.

1 job        real   2m27.929s    user   2m11.352s    sys    0m11.964s    
2 jobs       real   1m22.901s    user   2m13.800s    sys    0m9.532s
3 jobs       real   1m6.434s     user   2m29.024s    sys    0m10.532s
4 jobs       real   0m59.847s    user   2m50.336s    sys    0m12.656s
5 jobs       real   0m58.657s    user   3m24.384s    sys    0m14.112s
6 jobs       real   0m57.100s    user   3m51.776s    sys    0m16.128s
7 jobs       real   0m56.304s    user   4m15.500s    sys    0m16.992s
8 jobs       real   0m53.513s    user   4m38.456s    sys    0m17.724s
9 jobs       real   0m53.371s    user   4m37.344s    sys    0m17.676s
10 jobs      real   0m53.350s    user   4m37.384s    sys    0m17.752s
11 jobs      real   0m53.834s    user   4m43.644s    sys    0m18.568s
12 jobs      real   0m52.187s    user   4m32.400s    sys    0m17.476s
13 jobs      real   0m53.834s    user   4m40.900s    sys    0m17.660s
14 jobs      real   0m53.901s    user   4m37.076s    sys    0m17.408s
15 jobs      real   0m55.975s    user   4m43.588s    sys    0m18.504s
16 jobs      real   0m53.764s    user   4m40.856s    sys    0m18.244s
inf jobs     real   0m51.812s    user   4m21.200s    sys    0m16.812s

기본 결과 :

  • 코어 수로 확장하면 성능이 거의 선형 적으로 향상됩니다. 실시간은 2.5 분에서 1.0 분 (2.5 배 빠름)으로 줄었지만 컴파일 시간은 2.11 분에서 2.50 분으로 늘어났습니다. 시스템은이 비트에서 추가로드를 거의 발견하지 못했습니다.
  • 코어 수에서 스레드 수로 확장하면 사용자로드가 2.50 분에서 4.38 분으로 엄청나게 증가했습니다. 이 거의 두 배가되는 것은 다른 컴파일러 인스턴스가 동시에 동일한 CPU 리소스를 사용하기를 원했기 때문일 가능성이 높습니다. 시스템에 요청 및 작업 전환이 더 많이로드되어 사용 시간이 17.7 초로 늘어납니다. 이점은 컴파일 시간 53.5 초에서 약 6.5 초로 12 % 속도 향상을 가져옵니다.
  • 스레드 수에서 이중 스레드 수로 확장해도 속도가 크게 향상되지 않았습니다. 12와 15의 시간은 무시할 수있는 통계적 이상일 가능성이 높습니다. 소요 된 총 시간은 시스템 시간과 마찬가지로 약간 증가합니다. 둘 다 작업 전환 증가로 인한 것 같습니다. 이것에는 이점이 없습니다.

내 추측으로는 컴퓨터에서 다른 작업을 수행하는 경우 코어 수를 사용합니다. 그렇지 않은 경우 스레드 수를 사용하십시오. 그것을 초과하면 이점이 없습니다. 언젠가는 메모리가 제한되고 그로 인해 붕괴되어 컴파일 속도가 훨씬 느려집니다. "inf"라인은 훨씬 나중에 추가되어 8 개 이상의 작업에 대해 약간의 열 스로틀 링이 있다는 의혹을 받았습니다. 이것은이 프로젝트 크기에 대해 유효한 메모리 또는 처리량 제한이 없음을 보여줍니다. 그러나 컴파일 할 8GB의 메모리가 주어진 작은 프로젝트입니다.


stackoverflow.com/questions/56272639/… 에 따르면 CPU보다 많은 작업을 실행하는 이점을 얻을 수 있지만 작업이 네트워크 I / O를 기다리는 데 상당한 시간을 소비하는 경우에만 가능합니다. 컴파일 작업의 경우에는 그렇지 않습니다.
ivan_pozdeev

30

나는 개인적 make -j n으로 n이 "코어 수"+ 1 인 경우를 사용합니다.

그러나 과학적인 설명은 할 수 없습니다. 같은 설정을 사용하는 사람들을 많이 보았고 지금까지 꽤 좋은 결과를 얻었습니다.

어쨌든 일부 메이크 체인은 단순히 --jobs옵션 과 호환되지 않고 예기치 않은 결과를 초래할 수 있으므로주의해야 합니다. 이상한 종속성 오류가 발생하는 make경우 --jobs.


19
설명 (과학성을 보증 할 수 없음)은 "+ 1"이 다른 n 개의 작업 중 누군가가 I / O를 수행하는 동안 실행되는 추가 작업을 제공한다는 것입니다.
Laurynas Biveinis

@LaurynasBiveinis :하지만 작업은 항상 다른 코어에서 실행되고 있으며, 작업이 더 오랜 기간 동안 동일한 코어에있을 수있는 더 보수적 인 설정보다 더 자주 실행됩니다. 장점과 단점은 ... 여기있다
krlmlr은

1
코어 수 + 1도 기본 설정입니다. 한 가지 문제는 합리적으로 큰 시스템에서 make가 연결을 지연시키고 모든 연결 단계를 함께 수행하는 것처럼 보인다는 것 입니다. 이 시점에서 RAM이 부족합니다. Bah!
bobbogo

4
일부 메이크 체인은 단순히 --jobs 옵션과 호환되지 않습니다-> 이는 종속성이 누락되었음을 의미합니다. 이것을 얻으면 makefile을 수정하십시오.
dascandy

7

궁극적으로 빌드에 사용할 최적의 수를 결정하기 위해 몇 가지 벤치 마크를 수행해야하지만 CPU만이 중요한 리소스가 아님을 기억하십시오!

예를 들어 디스크에 크게 의존하는 빌드가있는 경우 멀티 코어 시스템에서 많은 작업을 생성하는 것이 실제로 더 느릴 수 있습니다 . 디스크가 모든 서비스를 제공하기 위해 디스크 헤드를 앞뒤로 이동하는 추가 작업을 수행해야하기 때문입니다. 다양한 작업 (OS가 디스크 캐시를 얼마나 잘 처리하는지, 디스크의 기본 명령 대기열 지원 등과 같은 많은 요인에 따라 다름).

그리고 "실제"코어와 하이퍼 스레딩이 있습니다. 각 하이퍼 스레드에 대한 작업 생성의 이점이있을 수도 있고 그렇지 않을 수도 있습니다. 다시 한 번, 벤치 마크를 통해 알아 내야합니다.

내가 특별히 #cores + 1을 시도했다고 말할 수는 없지만 우리 시스템 (Intel i7 940, 4 개의 하이퍼 스레드 코어, 많은 RAM 및 VelociRaptor 드라이브)과 우리의 빌드 (대규모 C ++ 빌드는 CPU와 I / O 바운드) -j4와 -j8 사이에는 거의 차이가 없습니다. (아마 15 % 더 나아질 수도 있지만 ...)

점심을 먹으러 나가는 경우 -j8을 사용하지만 시스템을 구축하는 동안 다른 용도로 시스템을 사용하려면 더 낮은 숫자를 사용합니다. :)


1
훌륭해 보이지만 왜 매번 + 15 %를 사용하지 않는지 혼란 스럽습니다-j 8
sg

1
@sg : j8은 제가 원래 포스트에서 설명한 시스템에 정말 부담이되었습니다 ... 머신은 여전히 사용할 수 있었지만 확실히 응답 성이 떨어졌습니다. 따라서 다른 작업 (일반적으로 다른 코드에서 작업하고 가끔 단일 DLL 빌드)에 대해 대화 형으로 사용하고 싶다면 대화 형 비트를 위해 몇 개의 코어를 예약합니다.
ijprest

@sg : 이것은 우리의 최신 시스템에서는 문제가되지 않습니다 ... 나는 대부분이 현재 SSD를 실행하고 있기 때문이라고 생각합니다. (이제 SSD로 갈 예정 이니 완전히 CPU에 묶여 있다고 생각합니다 ... 거의 개선없이 RAM 드라이브에 완전히 구축해 보았습니다.)하지만 그래도 코어 몇 개는 무료로 남겨 둘 것입니다. 포 그라운드에서 단순한 텍스트 편집 이상의 작업을 수행합니다.
ijprest

5

방금 Foxconn M / B와 4GB의 G-Skill 메모리가있는 Athlon II X2 Regor 프로세서를 받았습니다.

다른 사람들이 내 사양을 볼 수 있도록이 끝에 'cat / proc / cpuinfo'와 'free'를 넣었습니다. 4GB RAM을 갖춘 듀얼 코어 Athlon II x2입니다.

uname -a on default slackware 14.0 kernel is 3.2.45.

다음 단계 커널 소스 (linux-3.2.46)를 / archive4에 다운로드했습니다.

추출 ( tar -xjvf linux-3.2.46.tar.bz2);

디렉토리 ( cd linux-3.2.46); 로 cd'd

기본 커널의 구성을 ( cp /usr/src/linux/.config .)에 복사했습니다 .

make oldconfig3.2.46 커널 구성을 준비하는 데 사용 됩니다.

그런 다음 -jX의 다양한 주문으로 make를 실행했습니다.

시간 명령 뒤에 make를 실행하여 각 실행의 타이밍을 테스트했습니다 (예 : 'time make -j2'). 각 실행 사이에 linux-3.2.46 트리를 'rm -rf'하고 다시 추출하고 기본 /usr/src/linux/.config를 디렉토리에 복사하고 make oldconfig를 실행 한 다음 'make -jX'테스트를 다시 수행했습니다. .

일반 "만들기":

real    51m47.510s
user    47m52.228s
sys     3m44.985s
bob@Moses:/archive4/linux-3.2.46$

위와 같지만 make -j2

real    27m3.194s
user    48m5.135s
sys     3m39.431s
bob@Moses:/archive4/linux-3.2.46$

위와 같지만 make -j3

real    27m30.203s
user    48m43.821s
sys     3m42.309s
bob@Moses:/archive4/linux-3.2.46$

위와 같지만 make -j4

real    27m32.023s
user    49m18.328s
sys     3m43.765s
bob@Moses:/archive4/linux-3.2.46$

위와 같지만 make -j8

real    28m28.112s
user    50m34.445s
sys     3m49.877s
bob@Moses:/archive4/linux-3.2.46$

'cat / proc / cpuinfo'결과 :

bob@Moses:/archive4$ cat /proc/cpuinfo
processor       : 0
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 0
cpu cores       : 2
apicid          : 0
initial apicid  : 0
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.91
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

processor       : 1
vendor_id       : AuthenticAMD
cpu family      : 16
model           : 6
model name      : AMD Athlon(tm) II X2 270 Processor
stepping        : 3
microcode       : 0x10000c8
cpu MHz         : 3399.957
cache size      : 1024 KB
physical id     : 0
siblings        : 2
core id         : 1
cpu cores       : 2
apicid          : 1
initial apicid  : 1
fdiv_bug        : no
hlt_bug         : no
f00f_bug        : no
coma_bug        : no
fpu             : yes
fpu_exception   : yes
cpuid level     : 5
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmo
v pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rd
tscp lm 3dnowext 3dnow constant_tsc nonstop_tsc extd_apicid pni monitor cx16 p
opcnt lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowpre
fetch osvw ibs skinit wdt npt lbrv svm_lock nrip_save
bogomips        : 6799.94
clflush size    : 64
cache_alignment : 64
address sizes   : 48 bits physical, 48 bits virtual
power management: ts ttp tm stc 100mhzsteps hwpstate

'무료'수익률 :

bob@Moses:/archive4$ free
             total       used       free     shared    buffers     cached
Mem:       3991304    3834564     156740          0     519220    2515308

1
무엇을 그냥 않습니다 make -j해당 시스템에합니까? Make는 부하를 확인하고 부하에 따라 프로세스 수를 조정합니다.
docwhat

1
make -j작업 수를 전혀 제한하지 않습니다. 이는 일반적으로 RAM에서 지원할 수있는 것보다 더 많은 작업이 빠르게 분기되므로 중대형 프로젝트에서 재앙입니다. 로드별로 제한해야하는 옵션은 다음 -l [load]과 같습니다.-j
Matt G

5

둘 다 틀리지 않았습니다. 자신과 컴파일하는 소프트웨어의 작성자와 평화를 유지하려면 (소프트웨어 수준 자체에서 다른 다중 스레드 / 단일 스레드 제한이 적용됨) 다음을 사용하는 것이 좋습니다.

make -j`nproc`

참고 : nproc시스템에서 사용 가능한 코어 / 스레드 (최신 CPU) 수를 반환하는 linux 명령입니다. 위와 같이 틱 아래에 놓으면 make 명령에 번호가 전달됩니다.

추가 정보 : 누군가가 언급했듯이 모든 코어 / 스레드를 사용하여 소프트웨어를 컴파일하면 말 그대로 상자가 거의 죽을 수 있으며 (응답하지 않음) 코어를 적게 사용하는 것보다 더 오래 걸릴 수 있습니다. 내가 여기에 게시 한 한 Slackware 사용자를 보았을 때 그는 듀얼 코어 CPU를 가지고 있었지만 여전히 최대 j 8 테스트를 제공했으며, 이는 j 2 (CPU가 사용할 수있는 하드웨어 코어 2 개만)에서 차이를 멈췄습니다. 따라서 응답하지 않는 상자를 피하기 위해 다음과 같이 실행하는 것이 좋습니다.

make -j`nproc --ignore=2`

이 출력 통과 할 nproc로를 make하고 그 결과 2 개 코어를 뺍니다.


3

심판처럼 :

에서 Spawning Multiple Build Jobs섹션 LKD :

여기서 n은 생성 할 작업의 수입니다. 일반적인 방법은 프로세서 당 하나 또는 두 개의 작업을 생성하는 것입니다. 예를 들어, 듀얼 프로세서 시스템에서는 다음을 수행 할 수 있습니다.

$ j4 만들기


끊어진 링크, Robert Love의 Linux Kernel Development의 인용문입니까?
Behrooz

네, 그 책에 있습니다.
Nan Xiao

1

내 경험상, 추가 작업을 추가 할 때 성능상의 이점이 있어야합니다. 이는 단순히 디스크 I / O가 CPU 외에 병목 현상 중 하나이기 때문입니다. 그러나 사용중인 디스크 유형 및 코어 수와 밀접하게 연결되어 있으므로 추가 작업 수를 결정하는 것은 쉽지 않습니다.


1

수년이 지난 후에도 이러한 답변의 대부분은 여전히 ​​옳습니다. 그러나 약간의 변화가있었습니다. 물리적 코어보다 더 많은 작업을 사용하면 이제 진정으로 상당한 속도 향상을 얻을 수 있습니다. Dascandy의 표에 대한 부록으로, Linux에서 AMD Ryzen 5 3600X로 프로젝트를 컴파일 한 시간입니다. (분말 장난감, c6f653ac3cef03acfbc44e8f29f11e1b301f1ca2 커밋)

나는 스스로를 확인하는 것이 좋지만 다른 사람들의 의견을 통해 작업 수에 논리적 코어 수를 사용하는 것이 Zen에서 잘 작동한다는 것을 발견했습니다. 그와 함께 시스템은 응답 성을 잃지 않는 것 같습니다. 나는 이것이 최신 Intel CPU에도 적용된다고 생각합니다. SSD도 있으므로 CPU를 직접 테스트 해 볼 가치가 있습니다.

scons -j1 --release --native  120.68s user 9.78s system 99% cpu 2:10.60 total
scons -j2 --release --native  122.96s user 9.59s system 197% cpu 1:07.15 total
scons -j3 --release --native  125.62s user 9.75s system 292% cpu 46.291 total
scons -j4 --release --native  128.26s user 10.41s system 385% cpu 35.971 total
scons -j5 --release --native  133.73s user 10.33s system 476% cpu 30.241 total
scons -j6 --release --native  144.10s user 11.24s system 564% cpu 27.510 total
scons -j7 --release --native  153.64s user 11.61s system 653% cpu 25.297 total
scons -j8 --release --native  161.91s user 12.04s system 742% cpu 23.440 total
scons -j9 --release --native  169.09s user 12.38s system 827% cpu 21.923 total
scons -j10 --release --native  176.63s user 12.70s system 910% cpu 20.788 total
scons -j11 --release --native  184.57s user 13.18s system 989% cpu 19.976 total
scons -j12 --release --native  192.13s user 14.33s system 1055% cpu 19.553 total
scons -j13 --release --native  193.27s user 14.01s system 1052% cpu 19.698 total
scons -j14 --release --native  193.62s user 13.85s system 1076% cpu 19.270 total
scons -j15 --release --native  195.20s user 13.53s system 1056% cpu 19.755 total
scons -j16 --release --native  195.11s user 13.81s system 1060% cpu 19.692 total
( -jinf test not included, as it is not supported by scons.)

Ryzen 5 3600X, Samsung 860 Evo SSD (SATA) 및 32GB RAM이 장착 된 Ubuntu 19.10에서 수행 된 테스트

마지막 메모 : 3600X를 가진 다른 사람들은 나보다 더 나은 시간을 얻을 수 있습니다. 이 테스트를 수행 할 때 에코 모드를 활성화하여 CPU 속도를 약간 줄였습니다.


0

예! 3950x에서 -j32를 실행하면 컴파일 시간이 절약됩니다! 컴파일하는 동안에도 유튜브 시청, 웹 브라우징 등을 아무런 차이없이 볼 수 있습니다. 프로세서는 1TB 970 PRO nvme 또는 1TB Auros Gen4 nvme 및 64GB의 3200C14에서도 항상 고정되지는 않습니다. 그래도 UI 현명한 느낌이 들지 않습니다. 가까운 장래에 예정된 대규모 프로젝트에서 -j48로 테스트 할 계획입니다. 아마 당신이 그러 하듯이 인상적인 개선을 기대합니다. 여전히 쿼드 코어를 가진 사람들은 동일한 이득을 얻지 못할 수도 있습니다 ....

Linus 자신은 방금 3970x로 업그레이드했으며 최저 달러를 걸 수 있습니다. 그는 적어도 -j64를 실행하고 있습니다.

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