web-dev-qa-db-ja.com

GNU make:ジョブの数はシステム内のCPUコアの数と同じにすべきですか?

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

クアッドコアシステムで-j4または-j5を使用する方が良いですか?

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

78
Johan

最善の方法は、特定の環境とワークロードでベンチマークを自分で行うことです。サイズに合うすべての回答には、変数が多すぎるようです(ソースファイルのサイズ/数、使用可能なメモリ、ディスクキャッシュ、ソースディレクトリとシステムヘッダーが異なるディスクにあるかどうかなど)。

私の個人的な体験(2コアMacBook Proでの)では、-j2は-j1よりも大幅に高速ですが、それ以上(-j3、-j4など)は測定可能なほど高速化されません。私の環境では、「jobs == number of cores」が適切な答えのようです。 (YMMV)

52
David Gelhar

ハイパースレッディングラップトップを使用して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分に大幅に増加しました。このほぼ2倍になるのは、他のコンパイラインスタンスが同じCPUリソースを同時に使用したいためです。システムは要求とタスクの切り替えでもう少し負荷がかかっているため、17.7秒の使用時間になります。利点は、コンパイル時間53.5秒で約6.5秒であり、12%の高速化を実現します。
  • スレッドカウントからスレッドカウントを2倍にスケーリングしても、大幅な高速化は行われませんでした。 12および15の時間は、ほとんどの場合、無視できる統計的な異常です。合計所要時間は、システム時間と同様にわずかに増加します。どちらも、タスクスイッチングの増加によるものと考えられます。これには利点はありません。

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

49
dascandy

私は個人的にmake -j nを使用します。nは「コアの数」+1です。

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

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

29
ereOn

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

たとえば、ディスクに大きく依存するビルドがある場合、マルチコアシステムで大量のジョブを生成すると、実際にはslowerになる可能性があります。 OSがディスクキャッシュを処理する方法、ディスクによるネイティブコマンドキューイングのサポートなど、多くの要因に応じて、さまざまなジョブすべてに対応するために行き来します。

そして、「実際の」コアとハイパースレッディングがあります。ハイパースレッドごとにジョブを生成してもメリットがある場合とない場合があります。繰り返しますが、あなたはそれを見つけるためにベンチマークをする必要があります。

#cores + 1を具体的に試したとは言えませんが、システム(Intel i7 940、4つのハイパースレッドコア、大量のRAM、VelociRaptorドライブ)とビルド(大規模CPUとI/Oを交互に使用するC++ビルド)-j4と-j8の違いはほとんどありません。 (多分15%良くなりますが、2倍近くはありません。)

昼食に出かける場合は-j8を使用しますが、構築中にシステムを他の何かに使用したい場合は、小さい数字を使用します。 :)

7
ijprest

Foxconn M/Bと4GBのGスキルメモリを備えた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'd(cd linux-3.2.46);

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

中古 make oldconfig 3.2.46カーネル設定を準備します。

その後、-jXのさまざまな呪文を使用してmakeを実行しました。

Timeコマンドの後にmakeを発行して、各実行のタイミングをテストしました(例: 'time make -j2')。各実行の間に、linux-3.2.46ツリーを「rm -rf」して再抽出し、デフォルトの/usr/src/linux/.configをディレクトリにコピーし、make oldconfigを実行してから、「make -jX」テストを再度実行しました。

単純な「make」:

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
4
sloMoses

参照として:

[〜#〜] lkd [〜#〜]Spawning Multiple Build Jobsセクションから:

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

$ make j4

3
Nan Xiao

どちらも間違っていません。自分自身とコンパイルしているソフトウェアの作成者と安心するために(ソフトウェアレベル自体に異なるマルチスレッド/シングルスレッドの制限が適用されます)、以下を使用することをお勧めします。

make -j`nproc`

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

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

make -j`nproc --ignore=2`

これは、nprocの出力をmakeに渡し、その結果から2コアを引きます。

1
Digital Lucifer

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

1
Matt