GNU make: должно ли количество заданий равняться количеству ядер процессора в системе?

Кажется, есть некоторые споры о том, Должно ли количество заданий в GNU make равняться количеству ядер, или если вы можете оптимизировать время сборки, добавив одно дополнительное задание, которое может быть поставлено в очередь, пока другие "работают".

лучше использовать -j4 или -j5 на четырехъядерной системе?

вы видели (или сделали) какой-либо бенчмаркинг, который поддерживает один или другой?

7 ответов


Я бы сказал, что лучше всего сделать, это проверить его самостоятельно на вашей конкретной среде и рабочей нагрузке. Кажется, что слишком много переменных (размер / количество исходных файлов, доступная память, кэширование диска, находится ли ваш исходный каталог и системные заголовки на разных дисках и т. д.) для ответа "один размер подходит всем".

мой личный опыт (на 2-ядерном MacBook Pro) заключается в том, что-j2 значительно быстрее, чем-j1, но за его пределами (-j3,- j4 и т. д.) нет измеримых ускорение. Поэтому для моей среды" jobs == количество ядер " кажется хорошим ответом. (YMMV)


Я запустил свой домашний проект на своем 4-ядерном ноутбуке с hyperthreading и записал результаты. Это довольно тяжелый для компилятора проект, но он включает в себя модульный тест 17.7 секунд в конце. Компиляторы не очень интенсивны для ввода-вывода; доступно очень много памяти,а если нет, то на быстром 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 x так же быстро), но время, затраченное на компиляцию, увеличилось с 2,11 до 2,50 минуты. Система едва заметила какую-либо дополнительную нагрузку в этом бит.
  • масштабирование от подсчета ядра до подсчета потоков значительно увеличило нагрузку на пользователя, с 2.50 минут до 4.38 минут. Это почти удвоение, скорее всего, потому, что другие экземпляры компилятора хотели использовать те же ресурсы процессора одновременно. Система становится немного более загруженной запросами и переключением задач, в результате чего она перейти к 17.7 секунд времени. Преимущество составляет около 6,5 секунд на время компиляции 53,5 секунд, что делает для ускорения 12%.
  • масштабирование от подсчета потоков до двойного подсчета потоков не дало значительного ускорения. Времена в 12 и 15 являются наиболее вероятными статистическими аномалиями, которые вы можете игнорировать. Общее время увеличивается так же незначительно, как и системное время. Оба, скорее всего, из-за увеличения переключения задач. В этом нет никакой пользы.

мой угадайте прямо сейчас: если вы делаете что-то еще на своем компьютере, используйте core count. Если нет, используйте счетчик потоков. Превышение его не показывает никакой пользы. В какой-то момент они станут ограниченной памятью и свернутся из-за этого, что сделает компиляцию намного медленнее. Строка " inf " была добавлена намного позже, что дало мне подозрение, что для заданий 8+ было некоторое тепловое дросселирование. Это показывает, что для этого размера проекта нет ограничения памяти или пропускной способности. Это небольшой проект хотя, учитывая 8GB памяти для компиляции.


Я, лично, использую make -j n где n - "количество ядер" + 1.

Я не могу, однако, дать научное объяснение: я видел много людей, использующих те же настройки, и они дали мне довольно хорошие результаты до сих пор.

в любом случае, вы должны быть осторожны, потому что некоторые цепочки просто несовместимы с , и может привести к неожиданным результатам. Если вы испытываете странные ошибки зависимости, просто попробуйте make без --jobs.


в конечном счете, вам придется сделать некоторые тесты, чтобы определить лучшее число для вашей сборки, но помните, что CPU-не единственный ресурс, который имеет значение!

Если у вас есть сборка, которая сильно зависит от диска, например, то создание множества заданий в многоядерной системе может быть медленнее, поскольку диск должен будет выполнять дополнительную работу, перемещая головку диска вперед и назад, чтобы обслуживать все различные задания (в зависимости от множества факторов, например, как ну, ОС обрабатывает диск-кэш, поддержку очереди собственных команд на диске и т. д.).

и тогда у вас есть" реальные " ядра против гиперпотоков. Вы можете или не можете извлечь выгоду из заданий нереста для каждого гиперпотока. Опять же, вам придется проверить, чтобы узнать.

Я не могу сказать, что я специально пробовал #ядер + 1, но на наших системах (Intel i7 940, 4 hyperthreaded ядра, много ОЗУ и VelociRaptor диски) и наша сборка (крупномасштабная сборка C++ это поочередно CPU и I / O связаны) существует очень небольшая разница между-j4 и-j8. (Возможно, на 15% лучше... но далеко не в два раза лучше.)

Если я уезжаю на обед, я буду использовать -j8, но если я хочу использовать свою систему для чего-либо еще, пока она строится, я буду использовать меньшее число. :)


я только что получил Athlon II X2 Regor proc с Foxconn M / B и 4gb памяти G-Skill.

я поставил "cat/proc / cpuinfo" и "free" в конце этого, чтобы другие могли видеть мои спецификации. Это двухъядерный Athlon II x2 с 4 ГБ оперативной памяти.

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);

диск D в директорию (cd linux-3.2.46);

и скопировал ядро по умолчанию config over (cp /usr/src/linux/.config .);

используется make oldconfig для подготовки конфигурации ядра 3.2.46;

затем побежал сделать с различными заклинаниями-jX.

я проверил тайминги каждого запуска, выполнив команду make после команды time, например, 'time make-j2'. Между каждым запуском я "rm-rf" дерево linux-3.2.46 и повторно вычитал его, скопировал default /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

просто как ref:

С на LKD:

где n-количество заданий для создания. Обычная практика заключается в создании одного или двух заданий на процессор. Например, на двухпроцессорной машине можно сделать

$ J4 не сделать


по моему опыту, при добавлении дополнительных заданий должны быть некоторые преимущества производительности. Это просто потому, что дисковый ввод-вывод является одним из шеек бутылки, кроме процессора. Однако нелегко решить количество дополнительных заданий, поскольку оно тесно связано с количеством используемых ядер и типов диска.