# включити всі файли .cpp в один блок компіляції?


75

Нещодавно у мене була причина працювати з деякими проектами Visual Studio C ++ із звичайними конфігураціями налагодження та випуску, а також "Release All" та "Debug All", яких я ніколи раніше не бачив.

Виявляється, автор проектів має єдиний ALL.cpp, який # включає всі інші .cpp файли. * Усі конфігурації просто створюють цей файл ALL.cpp. Звичайно, це виключається зі звичайних конфігурацій, і звичайні конфігурації не створюють ALL.cpp

Я просто подумав, чи це звичайна практика? Яку користь це приносить? (Моя перша реакція полягала в тому, що неприємно пахло.)

З якими підводними каменями ви, мабуть, стикаєтесь? Я можу придумати одне: якщо у вас є. Анонімні простори імен у .cpps, вони більше не є "приватними" для цього cpp, але тепер їх видно і в інших cpps?

Усі проекти будують бібліотеки бібліотек DLL, тому наявність даних в анонімних просторах імен не буде гарною ідеєю, чи не так? Але функції були б нормальні?


2
Безумовно патологічний; Я можу лише здогадуватися про причину, чому хтось може це зробити (якщо ви, навпаки, можете запитати їх безпосередньо, ви повинні). Зазвичай в C ++ ви хочете зробити навпаки, зберігайте не тільки файли реалізації, але й заголовки, добре відокремлені. (Типовою пасткою проектів на C ++ є "#include spaghetti", кожен файл заголовка залежно від кожного іншого.) Можливо, для стрес-тестування компілятора?
Моренділ

1
Існує коротке відео, яке представляє різницю в часі в unionbuild.
Özgür

2
Вступ про "Unity Builds", а також переваги, недоліки та повну інтеграцію CMake можна знайти на cheind.wordpress.com . hth, Christoph
cheind

Наша офіційна збірка завжди потребує відновлення, тому я вважаю, що такий підхід може значно покращити продуктивність збірки. Але оскільки офіційні збірки в основному використовуються розробниками, але UnityBuild згенерований pdbs може бути недійсним для коду no-unionbuild. (Ми не хочемо розвиватися з конфігурацією побудови єдності, так?)
Байє

Зовсім іншою причиною включення деяких файлів реалізації в інший файл реалізації є: ці файли можуть бути автоматично сформовані. Набагато простіше автоматично згенерувати цілий файл, ніж мати справу із введенням змін у існуючий код.
Сергій К.

Відповіді:


61

Деякі називають це (і з можливістю google) як "Створення єдиності". Він пов'язує шалено швидко, а також компілює досить швидко. Це чудово підходить для збірок, для яких вам не потрібно повторювати, як збірка випуску з центрального сервера, але це не обов’язково для покрокової збірки.

І це ПІТА підтримувати.

EDIT: ось перше посилання на Google для отримання додаткової інформації: http://buffered.io/posts/the-magic-of-unity-builds/

Все, що робить це швидким, полягає в тому, що компілятору потрібно лише один раз прочитати все, скомпілювати, потім зв’язати, а не робити це для кожного файлу .cpp.

Брюс Доусон набагато краще пише про це у своєму блозі: http://randomascii.wordpress.com/2014/03/22/make-vc-compiles-fast-through-parallel-compilation/


27
Це не тільки через введення-виведення. Кожен окремий файл .cpp часто включає багато файлів заголовків. Якщо ви компілюєте їх окремо, то компілюєте код у файлах заголовків кілька разів - по одному для кожного файлу .o. Якщо ви використовуєте "Unity Build", то ці заголовкові файли та все інше компілюються лише один раз.
Френк

6
Е-е ... це підпадає під I / O. Але так, це точніше.
MSN

8
Компіляції зазвичай не пов’язані з операціями вводу-виводу, якщо у вас недостатньо пам’яті. Дивіться мою відповідь нижче. Кеш диска працює. Пост, пов’язаний із посиланням, витрачає багато часу на софістику, щоб пояснити, наскільки поганий дисковий ввід / вивід, але це не має значення через кеш диска. Крім того, компіляція коду у файлах заголовків кілька разів повністю відрізняється від вводу-виводу. Проблема полягає у надмірній компіляції, надлишок вводу-виводу насправді ніколи не відбувається. Деякі небезпеки побудови єдності висвітлюються тут: randomascii.wordpress.com/2014/03/22/…
Брюс Доусон

1
Цікаво, чи можна було б, використовуючи CMake, генерувати файл .cpp build build з переліку джерел, що подаються в ціль. Зрештою, CMake вже має всю цю інформацію. Мені також цікаво, як все це змінюється при використанні накопичувачів флеш-пам’яті замість обертових накопичувачів, але більшість людей вже зауважили, що не проблема необробленого вводу-виводу, а багаторазова компіляція. У збірці, що не відрізняється єдністю, я, звичайно, помітив поліпшення роботи флешок для необробленого вводу-виводу.
легалізуйте

3
ще одна річ - побудова єдності не потрібно робити з одним вихідним файлом єдності (наприклад, цільовий файл 100 може бути побудований як 10 файлів єдності, кожен з яких 10 оригінальних). https://github.com/sakra/cotire дає вам змогу контролювати, скільки вихідних файлів єдності використовується. Також перегляньте https://github.com/onqtam/ucm - обгортку котире для полегшення використання збірки єдності (та багато іншого).
onqtam

57

Unity будує покращені швидкості збірки з трьох основних причин. Перша причина полягає в тому, що всі файли загальних заголовків потрібно проаналізувати лише один раз. Багато проектів на C ++ мають багато файлів заголовків, які включаються більшістю або всіма файлами CPP, і надлишковий синтаксичний аналіз їх є основною вартістю компіляції, особливо якщо у вас багато коротких вихідних файлів. Попередньо скомпільовані файли заголовків можуть допомогти з цією вартістю, але зазвичай існує багато файлів заголовків, які не є попередньо скомпільованими.

Наступною основною причиною побудови єдності покращують швидкість збірки є те, що компілятор викликається менше разів. Виклик компілятора має певну вартість запуску.

Нарешті, зменшення надлишкового аналізу заголовка означає зменшення надлишкового коду коду для вбудованих функцій, тому загальний розмір об’єктних файлів менший, що робить зв’язок швидшим.

Збірки Unity також можуть дати кращий код коду.

Unity збирає НЕ швидше через зменшення дискового вводу-виводу. Я створив багато збірок за допомогою xperf, і я знаю, про що я говорю. Якщо у вас достатньо пам’яті, кеш-пам’ять диска ОС уникне зайвого вводу-виводу - подальші читання заголовка надходитимуть із кешу дискової ОС. Якщо у вас недостатньо пам’яті, то збірки об’єднань можуть навіть погіршити збірку, спричиняючи перевищення обсягу пам’яті компілятора доступною пам’яттю та виведення на сторінку.

Дисковий ввід-вивід є дорогим, тому всі операційні системи агресивно кешують дані, щоб уникнути надмірного введення-виведення диска.


1
Тут найбільш правильна відповідь. Для масових проектів не існує альтернативи швидкості побудови. BTW запропонував msbuild / LTCG збільшити час зв'язку з 4 хвилин до ночі! (Клангу було краще).
ChocoBilly

Зверніть увагу, що VS 2015 виправляє помилку, перелічену нижче, завдяки чому посилання LTCG працюють значно швидше - втричі швидше на деяких останніх масштабних тестах. connect.microsoft.com/VisualStudio/feedback/details/1064219/…
Брюс Доусон

Правильно. Компіляція С ++ повільна, тому що кожна компіляційна одиниця повинна бути скомпільована окремо. Чому компіляція С ++ займає так багато часу?
phuclv

7

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

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

Тим не менш, я, здається, пам’ятаю, що останні компілятори (Microsoft, Intel, але я не думаю, що сюди входить GCC) можуть виконати цю оптимізацію для декількох блоків компіляції, тому я підозрюю, що цей `` фокус '' непотрібний.

Тим не менш, було б цікаво дізнатись, чи справді є якась різниця.


2
Visual C ++ може оптимізувати всю програму за допомогою перемикача / LTCG (генерація коду часу зв'язку)
Роджер Ліпскомб

1
в ці дні GCC і clang також підтримують LTO
justin

Тоді це, звичайно, непотрібно.
Arafangion

Це переосмислює ШВИДКІСТЬ та переміщення головки накопичувача на жорсткому диску БАГАТО!
Петър Петров

1
Петър Петров: Чи є у вас якісь показники, які вказують на це? Це повинно збільшити швидкість, оскільки це означає, що немає необхідності в рекурсивному та багаторазовому відвідуванні, відкритті та синтаксичному аналізі файлів заголовків.
Arafangion

2

Я згоден з Брюсом; з мого досвіду я спробував реалізувати Unity Build для одного зі своїх проектів .dll, який мав тонну заголовків та багато .cpps; щоб знизити загальний час компіляції на VS2010 (вже вичерпав параметри додаткової збірки), але замість того, щоб скоротити час компіляції, у мене закінчилося пам’ять, а збірка навіть не змогла закінчити компіляцію.

Однак додати; Я виявив, що ввімкнення опції багатопроцесорної компіляції у Visual Studio цілком допомагає скоротити час компіляції; Я не впевнений, чи така можливість доступна для інших компіляторів платформ.


2
Якщо ви згодні і нічого не додаєте, схоже, це не має бути відповіддю. Це звучить більше як історія та коментар.
RacerNerd

1
Власне; Я мав намір додати коментар щодо власного досвіду з проблемою (щодо промислової потужності та розміру кодової бази); для тих, хто пробує те саме, оскільки ідея Unity Builds начебто створює враження, що це майже призведе до меншої компіляції; що не стосується великих проектів. Причина, чому ми б намагалися це зробити в першу чергу; але я ніхто, щоб виключати винятки та певні міркування щодо дизайну.
spforay


0

У нас є мультиплатформенний проект для MacOS та Windows. У нас є багато великих шаблонів та багато заголовків. Ми скоротили час побудови за допомогою Visual Studio 2017 msvc, використовуючи попередньо скомпільовані заголовки. Для MacOS ми намагалися кілька днів скоротити час складання, але попередньо скомпільовані заголовки лише скоротили час складання до 85%. Використання одного файлу .cpp було проривом. Ми просто створюємо цей ALL.cpp за допомогою сценарію. Наш ALL.cpp містить список включень усіх .cpp-файлів нашого проекту. Ми скорочуємо час складання до 30% за допомогою XCode 9.0. Єдиним недоліком було те, що нам доводилося давати імена всім приватним просторам імен одиниць компіляції в .cpp-файлах. Інакше місцеві імена зіткнуться.

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