Компілювання з 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 робочих місць буде чекати вводу-виводу, тому решта завдань будуть використовувати наявні ядра. Число більше, ніж сердечники, краще, і ви навіть можете піднятися на 2х . Дивіться також: Гну наводить -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.