Компілювання з g ++ з використанням декількох ядер


174

Швидке запитання: що таке прапор компілятора, щоб дозволити g ++ нерегулярно створювати кілька екземплярів, щоб швидше збирати великі проекти (наприклад, 4 вихідні файли одночасно для багатоядерного процесора)?


Чи справді це допоможе? Усі мої завдання компіляції пов'язані з входом / виводом, а не з процесором.
Брайан Кноблауч

5
Навіть якщо вони пов'язані з входом / виводом, ви, ймовірно, можете тримати навантаження вводу / виводу вище, коли трапляються важкі біти процесора (із лише одним екземпляром g ++ буде затишшя) і, можливо, отримати ефективність вводу / виводу, якщо планувальник має більше вибору щодо що читати з диска далі. Мій досвід показав, що розумне використання make -jмайже завжди призводить до певного поліпшення.
Flexo

1
@BrianKnoblauch Але на моїй машині (справжній або у VirtualBox), це пов'язано з процесором, я виявив, що процесор зайнятий командою 'top' при компілюванні.
大 宝剑

1
Навіть якщо вони пов'язані вводу / виводу, ми можемо використовувати прапор gcc '-pipe' для зменшення болю.
大 宝剑

щойно побачив це в google: gcc.gnu.org/onlinedocs/libstdc++/manual/…
Джим Майклс

Відповіді:


240

Це можна зробити за допомогою make - з gnu make це прапор -j (це також допоможе на однопроцесорній машині).

Наприклад, якщо вам потрібно зробити 4 паралельних завдання від make:

make -j 4

Ви також можете запустити gcc в трубі за допомогою

gcc -pipe

Це дозволить скласти етапи компіляції, що також допоможе зберегти сердечники.

Якщо у вас також доступні додаткові машини, ви можете перевірити distcc , який також збирає компіляції для цих.


36
Ви -j число повинно бути в 1,5 рази меншим числом ядер.
Марк Беквіт

2
Дякую. Я намагався передати "-j #" в gcc через CFLAGS / CPPFLAGS / CXXFLAGS. Я повністю забув, що "-j #" є параметром для GNU make (а не для GCC).
chriv

33
Чому опція -j для GNU Make повинна дорівнювати 1,5 x кількості ядер CPU?
бітек

28
Число 1,5 - через зазначену проблему, пов'язану з входом / виводом Це правило. Приблизно 1/3 робочих місць буде чекати вводу-виводу, тому решта завдань будуть використовувати наявні ядра. Число більше, ніж сердечники, краще, і ви навіть можете піднятися на . Дивіться також: Гну наводить -jаргументи
бездушний шум

4
@JimMichaels Це може бути тому, що залежність погано встановлена ​​у вашому проекті (ціль починає будуватись, навіть якщо її залежності ще не готові), так що лише послідовна збірка закінчується успішною.
Антоніо

42

Такого прапора немає, і якщо один суперечить філософії Unix: кожен інструмент виконує лише одну функцію та виконує її добре. Процеси компілятора нересту концептуально є завданням системи збирання. Напевно, ви шукаєте прапор -j (вакансії) для GNU make, a la

скласти -j4

Або ви можете використовувати pmake або подібні паралельні системи виготовлення.



3
"Unix педантизм не корисний" Добре, що тоді це було не педантизм, анонімний редактор. Відкотився назад. Рецензенти, будь ласка, приділіть більше уваги тому, що ви робите.
Гонки легкості по орбіті

12

Люди згадували, makeале bjamтакож підтримують подібну концепцію. Використання bjam -jxінструкцій bjam для створення xодночасних команд.

Ми використовуємо однакові сценарії збірки в Windows та Linux і використовуючи цю опцію, вдвічі скорочуємо час збирання на обох платформах. Приємно.


9

makeзробить це за вас. Вивчіть -jі -lперемикачі на сторінці людини. Я не думаю, що g++це паралельно.


+1 для згадування -lваріанту (не починає нову роботу, якщо всі попередні завдання не припиняються). В іншому випадку здається, що завдання Linker починається не з усіх вбудованих файлів об'єктів (оскільки деякі компіляції все ще тривають), так що завдання Linker завершується невдачею.
NGI

8

Якщо ви використовуєте make, видайте питання -j. Від man make:

  -j [jobs], --jobs[=jobs]
       Specifies the number of jobs (commands) to run simultaneously.  
       If there is more than one -j option, the last one is effective.
       If the -j option is given without an argument, make will not limit the
       number of jobs that can run simultaneously.

І найголовніше, що якщо ви хочете скриптувати або ідентифікувати кількість наявних ядер (залежно від вашого оточення, і якщо ви працюєте в багатьох середовищах, це може сильно змінити), ви можете використовувати всюдисущу функцію Python cpu_count():

https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count

Подобається це:

make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')

Якщо ви запитуєте, чому 1.5я цитую користувача artless-шум у коментарі вище:

Число 1,5 - через зазначену проблему, пов'язану з входом / виводом. Це правило. Приблизно 1/3 робочих місць буде чекати вводу-виводу, тому решта завдань будуть використовувати наявні ядра. Число більше, ніж сердечники, краще, і ви навіть можете піднятися на 2х.


5
Більшість користувачів Linux, ймовірно , вважають за краще коротше: make -j`nproc` з nprocв GNU Coreutils.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Якщо ви використовуєте SSD, введення / виведення не складе великої кількості проблем. Просто будуючи на коментарі Ciro вище, ви можете зробити це: make -j $(( $(nproc) + 1 ))(переконайтеся, що ви розмістили місця, де я є).
Ред К

Приємна пропозиція щодо використання python у системах, де nprocїх немає, наприклад, у manylinux1контейнерах, це економить додатковий час, уникаючи запуску yum update/ yum install.
гофлінг

7

distcc також може використовуватися для розповсюдження компіляцій не тільки на поточній машині, але і на інших машинах ферми, на яких встановлено distcc.


+1, distcc - це корисний інструмент для наявності в арсеналі для великих будівель.
Flexo

Схоже , що є деякі , які робота «як» DistCC , а також: stackoverflow.com/questions/5374106/distributed-make / ...
rogerdpack

3

Я не впевнений у g ++, але якщо ви використовуєте GNU Make, тоді "make -j N" (де N - це кількість створених ниток) дозволить одночасно запускати декілька завдань g ++ (так довго оскільки файли не залежать один від одного).


2
ні N іст не кількість ниток! Багато людей неправильно розуміють це, але -j Nрозповідає, скільки процесів одразу має бути породженим, а не потоковими. Ось чому вона не настільки ефективна, як MS cl -MT(дійсно багатопотокова).
Sebi2020

2

Паралельно GNU

Я робив синтетичний орієнтир для компіляції і не міг заважати писати Makefile, тому я використав:

sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"

Пояснення:

  • {.} бере аргумент введення та видаляє його розширення
  • -t виводить команди, які виконуються, щоб дати нам уявлення про прогрес
  • --will-cite видаляє запит на посилання програмного забезпечення, якщо ви публікуєте результати, використовуючи його ...

parallel настільки зручно, що я міг навіть перевірити часову позначку:

ls | grep -E '\.c$' | parallel -t --will-cite "\
  if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
    gcc -c -o '{.}.o' '{}'
  fi
"

xargs -Pтакож можна паралельно виконувати завдання, але трохи менше зручно робити маніпуляції з розширенням або виконувати з ним кілька команд : Виклик декількох команд через xargs

Паралельне зв’язування запитували за адресою: Чи може gcc використовувати декілька ядер при з'єднанні?

TODO: Я думаю, я десь прочитав, що компіляція може бути зведена до матричного множення, тому, можливо, також можливо прискорити компіляцію одного файлу для великих файлів. Але зараз я не можу знайти посилання.

Тестовано в Ubuntu 18.10.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.