GNU make:ジョブの数はシステムのCPUコアの数と等しくなければなりませんか?


87

GNU makeのジョブの数がコアの数と等しいと想定されているかどうか、または他のジョブが「動作」している間にキューに入れることができる1つのジョブを追加することでビルド時間を最適化できるかどうかについて、いくつかの論争があるようです。 。

それは良く使用することです-j4か、-j5クアッドコアシステム上で?

どちらか一方をサポートするベンチマークを見た(または行った)ことがありますか?


8
ヒントとして、make `nproc`CPUに依存しないスクリプトを作成するために使用できます:)
VivienG 2015

io-boundとcpu-boundのレシピが混在している場合は、NCPUよりもはるかに多くのものが必要になる可能性があります。-lXオプションの追加も検討してください。これは、「ハードウェアとタスクの作成に依存する」ことを除けば、実際には答えられる質問ではありません。
James Moore

技術的には改善が見られます。あなたは遅いディスク、十分なRAMとたくさんの小さなソースコードファイルを必要とします。10年前までに来やすくなりました。
ハンスパッサント2018年

回答:


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リソースを同時に使用したかったため、このほぼ2倍になる可能性があります。システムはリクエストとタスク切り替えでもう少し負荷がかかり、17.7秒の使用時間になります。利点は、53.5秒のコンパイル時間で約6.5秒であり、12%のスピードアップになります。
  • スレッド数からダブルスレッド数へのスケーリングでは、大幅なスピードアップはありませんでした。12と15の時間は、無視できる統計上の異常である可能性が最も高いです。かかる合計時間は、システム時間と同様に、これまでになくわずかに増加します。どちらも、タスク切り替えの増加が原因である可能性があります。これには何のメリットもありません。

今の私の推測:コンピューターで何か他のことをする場合は、コアカウントを使用してください。そうでない場合は、スレッド数を使用してください。それを超えてもメリットはありません。ある時点で、それらはメモリが制限され、そのために崩壊し、コンパイルがはるかに遅くなります。「inf」行はかなり後の日付で追加され、8つ以上のジョブに熱スロットリングがあったのではないかと疑われました。これは、このプロジェクトサイズでは、メモリやスループットの制限が有効になっていないことを示しています。ただし、コンパイルするメモリが8 GBであることを考えると、これは小さなプロジェクトです。


stackoverflow.com/questions/56272639/…によると、タスクがネットワークI / Oの待機にかなりの時間を費やしている場合にのみ、CPUよりも多くのタスクを実行できるという利点があります。ただし、コンパイルタスクの場合はそうではありません。
ivan_pozdeev

30

私は個人的に、make -j nnが「コアの数」+1である場合に使用します。

しかし、科学的な説明はできません。同じ設定を使用している人をたくさん見たことがあり、これまでのところかなり良い結果が得られています。

とにかく、いくつかのメイクチェーンは単に--jobsオプションと互換性がなく、予期しない結果につながる可能性があるため、注意する必要があります。奇妙な依存関係エラーが発生している場合は、makeなしで試してください--jobs


19
説明(ただし、その科学性を保証することはできません)は、「+ 1」は、他のn個のジョブのいずれかがI / Oを実行しているときに実行される追加のジョブを提供するというものです。
Laurynas Biveinis 2010年

@LaurynasBiveinis:しかし、ジョブは常に異なるコアで実行されます。少なくとも、ジョブが同じコアに長期間留まる機会が与えられる、より保守的な設定よりも頻繁に実行されます。長所と短所が...ここにあります
krlmlrは、

1
コア数+1も私のデフォルト設定です。1つの問題は、適度に大規模なシステムでは、makeがリンクを遅らせ、すべてのリンク手順を一緒に実行するように見えることです。この時点で、RAMが不足しています。ああ!
bobbogo 2014年

4
一部のmake-chainは、単に--jobsオプションと互換性がありません->これは、依存関係が欠落していることを意味します。これを取得した場合は、メイクファイルを修正してください。
dascandy 2015

7

最終的には、ビルドに使用する最適な数を決定するためにいくつかのベンチマークを実行する必要がありますが、重要なリソースはCPUだけではないことに注意してください。

たとえば、ディスクに大きく依存するビルドがある場合、マルチコアシステムで多くのジョブを生成するのは実際には遅くなる可能性があります。これは、ディスクがすべてを提供するためにディスクヘッドを前後に移動する余分な作業を行う必要があるためです。さまざまなジョブ(OSがディスクキャッシュをどの程度適切に処理するか、ディスクによるネイティブコマンドキューイングのサポートなど、多くの要因によって異なります)。

そして、ハイパースレッディングに対して「実際の」コアがあります。ハイパースレッドごとにジョブを生成することでメリットが得られる場合と得られない場合があります。繰り返しになりますが、調べるにはベンチマークを行う必要があります。

特に#cores + 1を試したとは言えませんが、私たちのシステム(Intel i7 940、4つのハイパースレッドコア、大量のRAM、VelociRaptorドライブ)とビルド(CPUとIを交互に使用する大規模なC ++ビルド)で/ Oバウンド)-j4と-j8の間にほとんど違いはありません。(おそらく15%優れています...しかし、2倍近くはありません。)

昼食に出かける場合は-j8を使用しますが、システムの構築中に他の目的でシステムを使用する場合は、より低い数値を使用します。:)


1
素晴らしいようですが、なぜあなたが毎回+ 15%を使用しないのか混乱しています-j 8
sg

1
@sg:j8は、元の投稿で説明したシステムに本当に負担をかけていました...マシンはまだ使用可能でしたが、応答性は明らかに低下していました。したがって、他のタスク(通常は他のコードでの作業、場合によっては単一のDLLビルド)でインタラクティブに使用したい場合は、インタラクティブビット用にいくつかのコアを予約します。
ijprest 2014年

@sg:これは新しいシステムではそれほど問題ではありません...主にSSDを実行していることが原因だと思います。(SSDに移行するため、完全にCPUに縛られていると思います...ほとんど改善せずにRAMドライブ上に完全に構​​築しようとしました。)しかし、私がそうであれば、まだいくつかのコアを空けておきます。フォアグラウンドでの単純なテキスト編集以上のことを行います。
ijprest 2014年

5

Foxconn M / Bと4GBのG-Skillメモリを搭載したAthlonII X2 Regorprocを入手しました。

この最後に「cat / proc / cpuinfo」と「free」を付けて、他の人が私の仕様を見ることができるようにします。これは、4GBのRAMを搭載したデュアルコアAthlon IIx2です。

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しました(cd linux-3.2.46);

デフォルトのカーネルの設定を(cp /usr/src/linux/.config .);にコピーしました。

make oldconfig3.2.46カーネル構成の準備に使用されます。

次に、-jXのさまざまなインカンテーションでmakeを実行しました。

timeコマンドの後に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 2013年

1
make -jジョブの数をまったく制限しません。これは通常、RAMでサポートできるよりも多くのジョブがフォークされるため、中規模または大規模のプロジェクトでは悲惨です。負荷によって制限する必要があるオプションは-l [load]、次の-j
Matt G

5

どちらも間違っていません。あなた自身とあなたがコンパイルしているソフトウェアの作者と平和になるために(異なるマルチスレッド/シングルスレッドの制限がソフトウェアレベル自体に適用されます)、私はあなたが使用することを提案します:

make -j`nproc`

注:nprocシステムで使用可能なコア/スレッド(最新のCPU)の数を返すLinuxコマンドです。上記のようにティック `の下に配置すると、その番号がmakeコマンドに渡されます。

追加情報:誰かが言ったように、ソフトウェアをコンパイルするためにすべてのコア/スレッドを使用すると、文字通りボックスがほぼ死ぬまで窒息する可能性があり(応答しない)、コアを少なくするよりも時間がかかる場合があります。ここに投稿したSlackwareユーザーの1人が見たように、彼はデュアルコアCPUを持っていましたが、j 8までのテストを提供し、j 2で違いがなくなりました(CPUが利用できるハードウェアコアは2つだけです)。したがって、応答しないボックスを回避するには、次のように実行することをお勧めします。

make -j`nproc --ignore=2`

これは、の出力通過するnprocまでにmake、その結果から、2つのコアを引きます。


3

ちょうどrefとして:

LKDのSpawning Multiple Build Jobsセクションから:

ここで、nはスポーンするジョブの数です。通常は、プロセッサごとに1つまたは2つのジョブを生成します。たとえば、デュアルプロセッサマシンでは、

$ make j4


壊れたリンク、Robert LoveによるLinuxカーネル開発からのこの引用ですか?
behrooz 2018年

はい、それはその本からです。
ナンシャオ

1

私の経験から、ジョブを追加すると、パフォーマンス上の利点がいくつかあるはずです。これは、ディスクI / OがCPU以外のボトルネックの1つであるためです。ただし、コアの数や使用されているディスクの種類と高度に相互接続されているため、追加のジョブの数を決定するのは簡単ではありません。


1

何年も経った今でも、これらの答えの大部分は正しいものです。ただし、少し変更がありました。物理コアよりも多くのジョブを使用すると、真に大幅なスピードアップが実現します。Dascandyの表の補足として、Linux上のAMD Ryzen 53600Xでプロジェクトをコンパイルするときがあります。(パウダートイ、コミットc6f653ac3cef03acfbc44e8f29f11e1b301f1ca2)

自分で確認することをお勧めしますが、他の人からの入力により、ジョブ数に論理コア数を使用するとZenでうまく機能することがわかりました。それに加えて、システムは応答性を失うようには見えません。これは最近のIntelCPUにも当てはまると思います。私も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)、および32GBRAMを搭載したUbuntu19.10で実行されたテスト

最後の注意:3600Xを持っている他の人は、私よりも良い時間を得るかもしれません。このテストを行うとき、私はエコモードを有効にして、CPUの速度を少し下げました。


0

はい!3950xで-j32を実行すると、コンパイル時間が何時間も節約されます。コンパイル中もYouTubeを見たり、ウェブを閲覧したりすることができます。1TB 970 PROnvmeまたは1TBAuros Gen4 nvmeと64GBの3200C14を使用しても、プロセッサが常に固定されているとは限りません。たとえそうだとしても、私はUIに関しては気づいていません。近い将来、いくつかの大きなプロジェクトで-j48を使用してテストする予定です。おそらくあなたがそうするように、私はいくつかの印象的な改善を見ることを期待しています。まだクアッドコアを使用している場合は、同じゲインが得られない可能性があります。

Linus自身が3970xにアップグレードしたばかりで、最低額を賭けることができます。彼は少なくとも-j64を実行しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.