Оптимізація GCC - Gentoo Wiki

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

Що таке CFLAGS та CXXFLAGS?

Оскільки велика кількість пакетів, що становлять більшість систем Gentoo, написано на C і C++, адміністраторам слід правильно встановити ці дві змінні, оскільки вони дуже впливають на складання системи.

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

Як вони використовуються?

Як правило, змінні CFLAGS і CXXFLAGS встановлюються в оточенні під час виклику скрипта configure або за допомогою файлу make-файлів, створених програмою automake . У системах на базі Gentoo ці змінні встановлюються у файлі /etc/portage/make.conf. Змінні, встановлені в цьому файлі, експортуються в оточення програм, що запускаються portage - таким чином, всі пакети збираються, використовуючи ці параметри як основу.

У прикладі вище змінна CXXFLAGS встановлена ​​таким чином, що вона використовує всі параметри, встановлені змінною CFLAGS . Майже всі системи слід настроювати таким чином. Додаткові параметри для змінної CXXFLAGS менш поширені і зазвичай використовуються недостатньо широко для того, щоб було сенс встановлювати їх глобально.

Помилки

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

Параметри глобальної змінної CFLAGS , встановленої у файлі /etc/portage/make.conf , застосовуються до всіх пакетів у системі, тому адміністратори зазвичай встановлюють у цій змінній тільки найбільш загальні, широко використовувані параметри. Окремі пакети можуть змінювати ці параметри у файлі ebuild або в самій системі складання, створюючи остаточний набір прапорів, що подаються компілятору.

Тепер, знаючи деякі ризики, давайте подивимося деякі з розумних, безпечних оптимізації. Вони нададуть велику користь і розташують розробників наступного разу, коли повідомлятимете про проблему на Bugzilla. (Розробники зазвичай просять користувачів перекомпілювати пакет із мінімальною кількістю змінних CFLAGS для того, щоб визначити, чи продовжує проблема існувати. Запам'ятайте: агресивні прапори можуть зруйнувати код!)

Оптимізація

Метою використання CFLAGS та CXXFLAGS є створення коду, пристосованого під систему; він повинен відмінно функціонувати, будучи легковажним і швидким, якщо це можливо. Іноді це взаємовиключні умови, тому це керівництво дотримуватиметься комбінацій, про які відомо, що вони працюють добре. В ідеалі, вони легко доступні на будь-якій архітектурі CPU. Для ознайомлення агресивне використання прапора буде розглянуто пізніше. Не буде описуватися кожен параметр з керівництва GCC (їх дуже багато), але опишемо основні прапори, що найчастіше використовуються.

-ftree-vectorize is anoptimization option (докладніше на -O3 і -Ofast ), які встановлюють векторні прориви за допомогою вибраної ISA if possible. reason it isn't enabled at -O2 is that it doesn't always improve code, it can make code slower as well, and usually makes the code larger; it really depends on the loop etc.

Який вид CPU є у системі? Щоб дізнатися, введіть наступну команду:

  • Перша команда каже компілятору не виробляти лінківку (-c), і замість інтерпретувати опцію --help для уточнення параметрів командного рядка, показує які опції включені або відключені (-Q). У цьому випадку показані опції, які були включені для обраної мети:

  • Друга команда покаже директиви компілятора для побудови файлу заголовків, але без фактичного виконання, а результат роботи виведе на екран ( -### ). Висновок містить усі параметри оптимізації, а також вибрану архітектуру:

А це інший приклад для 64-розрядного AMD CPU:

Наступна за списком - змінна -O. Вона керує всім рівнем оптимізації. Зміна цієї змінної призводить до того, що компіляція коду займає більше часу і зможе зайняти набагато більше пам'яті, особливо коли рівень оптимізації збільшений.

Існує сім видів налаштувань змінної -O: -O0, -O1, -O2, -O3, -Os, -Og і -Ofast. Використовуйте лише одну з них /etc/portage/make.conf .

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

Давайте досліджуємо кожен рівеньоптимізації:

  • -O0 : Цей рівень (літера "O" та нуль за нею) відключає оптимізацію повністю і є рівнем за замовчуванням, якщо жодного рівня з префіксом -O не зазначено у змінних CFLAGS або CXXFLAGS . Це скорочує час компіляції і може покращити дані для налагодження, але деякі програми не працюватимуть належним чином без оптимізації. Ця опція не рекомендується, за винятком використання з метою налагодження.
  • -O1 : Це найпростіший рівень оптимізації. Компілятор спробує згенерувати швидкий код, що займає менше обсягу, без витрачання найбільшого часу компіляції. Він досить простий, але має завжди виконувати свою роботу.
  • -O2: Крок вперед від -O1.Рекомендованийрівень оптимізації, доки не знадобиться щось особливе. -O2 активує кілька додаткових прапорів до прапорів, активованих -O1 . З параметром -O2 компілятор спробує збільшити продуктивність коду без порушення розміру, і без витрачання великої кількості часу компіляції. На цьому рівні можуть бути використані SSE та AVX, але YMM-реєстри не будуть використовуватися доки не буде включена опція -ftree-vectorize .

  • -O3 : Це найбільший рівень оптимізації. Включає оптимізації, яка є дорогою з погляду часу компіляції та споживання пам'яті. Компіляція з -O3 не є гарантованим способом підвищення продуктивності, і насправді у багатьох випадках може призвести до уповільнення системи через великі двійкові файли та збільшення споживання пам'яті. -O3 також відомий тим, що ламає кілька пакетів. Використання -O3 не рекомендується.
  • -Os : На цьому рівні код буде оптимізований за обсягом. Він активує всі параметри -O2,які не призводять до збільшення розміру коду, що генерується. Він може бути корисним на комп'ютерах, які мають надзвичайно обмежений простір жорсткого диска та/або процесори з невеликим розміром кеша.
  • -Og : У GCC 4.8 було введено новий загальний рівень оптимізації -Og. Він задовольняє потребу у швидкій компіляції та має чудові можливості для налагодження, забезпечуючи при цьому прийнятний рівень продуктивності під час виконання. Загальний досвід розробки має бути кращим, ніж з рівнем оптимізації за умовчанням -O0. Зауважте, що -Og не означає -g, він просто відключає оптимізацію коду, яка може завадити налагодженню.
  • -Ofast : Нове в GCC 4.7, складається з -O3 плюс -ffast-math , -fno-protect-parens і -fstack-arrays . Цей параметр порушує сувору відповідність стандарту і не рекомендується для використання.

Загальновживувальний прапор -pipe. Цей прапор не впливає на код, що генерується, алеприскорюєпроцес компіляції. Він повідомляє компілятор, щоб той використовував конвеєр (pipe) замість тимчасових файлів протягом різних стадій компіляції, які використовують більшу кількість пам'яті. На системах з невеликою кількістю пам'яті GCC може завершити свою роботу. У цих випадках не використовуйте цей прапор.

-fomit-frame-pointer

Це дуже часто використовуваний прапор, призначений для того, щоб зменшити розмір коду, що генерується. Він включається на всіх рівнях з префіксом -O (за винятком -O0 ) на тих архітектурах, де це не ускладнює налагодження (таких як x86-64), але його, можливо, необхідно активувати. В цьому випадку додайте його до прапорів. Хоча керівництво GCC не вказує всі архітектури, але він включається з використанням параметра -O . Також потрібно явно активувати -fomit-frame-pointer для x86-32, якщо GCC версії нижче 4.6, або при використанні Os на x86 -32 з будь-якою версією GCC. Однак, використання -fomit-frame-pointer може зробити налагодження складним, або навіть неможливим.

Зокрема, це робить усунення неполадок у додатках, написаних на Java і скомпільованих в gcj, набагато складніше, хоча код, написаний на Java - не єдиний, який торкнеться використання цього прапора. Тому, коли використання цього прапора може допомогти, воно також ускладнює налагодження; трасування стека, зокрема, буде марним. Якщо не планується налагоджувати програми і немає інших змінних CFLAGS, пов'язаних з налагодженням, таких як -ggdb, то спробуйте використовувати -fomit-frame-pointer.

-msse, -msse2, -msse3, -mmmx, -m3dnow

Ці прапори дозволяють набори команд SIMD Extensions (SSE), SSE2, SSE3, MMX, та 3DNow! для архітектур x86 та x86-64. Вони використовуються в основному в мультимедіа, іграх, та інших обчислювальних задачах з інтенсивним використанням плаваючої точки, хоча вони також включають кілька інших математичних розширень. Ці набори команд надаються більшістю сучасних процесорів.

FAQ з оптимізації

Але я отримую кращу продуктивність із -funroll-loops -fomg-optimize!

Ні, людям тільки здається, що вони отримують кращу продуктивність, тому що хтось їх переконав у тому, що чим більше прапорів, тим краще. Агресивні прапори лише зашкодять програмам при глобальному використанні. Навіть GCC manual говорить, що використання параметрів -funroll-loops та -funroll-all-loops може збільшити обсяг коду та час його виконання. Хоча, з якихось причин, ці два прапори разом з прапорами -ffast-math , -fforce-mem , -fforce-addr , і подібними до них, продовжують користуватисяпопулярністю серед гонщиків, котрі хочуть підвищити почуття власної важливості.

Істина в тому, що це надзвичайно агресивні прапори. Перегляньте форуми Gentoo і Bugzilla, щоб побачити, що ці прапори можуть зробити: нічого хорошого!

Не потрібно використовувати ці прапори глобально, змінних CFLAGS і CXXFLAGS . Вони лише погіршать продуктивність. Може здатися, що вони зроблять систему більш високопродуктивною, що працює за останнім словом техніки, але вони нічого не роблять, крім роздування коду і призведуть до того, що ваші повідомлення про баги помітять як INVALID або WONTFIX.

Що з приводу рівнів оптимізації -O більш ніж 3?

Деякі користувачі хваляться навіть більшою продуктивністю, досягнутою використанням -O4, -O9, і так далі, але насправді рівні -O більші ніж 3 не мають жодного ефекту. Компілятор може приймати змінні CFLAGS, такі як -O4, але насправді нічого з ними не робить. Він тільки виконує оптимізацію до рівня -O3 і нічого більше:

Потрібно більше доказів? Дослідіть вихідний код:

Як можна побачити, будь-яке значення більше за трійку розглядається як -O3 .

Що щодо компіляції не на цільовій машині?

А що про надмірні прапори?

Часто змінні CFLAGS і CXXFLAGS, які включаються на різних рівнях -O, вказані надмірно /etc/portage/make.conf. Іноді це зроблено через непоінформованість, але також і для того, щоб уникнути відфільтровування прапорів або їх заміщення.

Фільтрування/заміщення прапорів використовується в багатьох ebuild-файлах, що знаходяться у дереві Portage. Зазвичай, це робиться тому що пакети не компілюються на певних рівнях -O, або коли вихідний код дуже чутливий до прапорів, що додатково використовуються. Ebuild-файл або відфільтровує деякі або всі змінні CFLAGS і CXXFLAGS або може замінити -O іншим рівнем.

Керівництво розробника Gentoo описує загалом, де і як працює фільтрація/заміщення прапорів.

Можливо обійти фільтрацію рівнів -O, надмірно перераховуючи прапори для певного рівня, наприклад -O3, роблячи такі речі як:

Однак, це не найрозумніша річ, яку можна зробити. CFLAGS відфільтровуються не дарма! Коли прапори фільтруються, це означає, що збирати пакет із цими прапорами небезпечно. Очевидно, щонебезпечнокомпілювати всю систему з -O3, якщо деякі з прапорів, включених на цьому рівні, викликають проблеми з певними пакетами. Отже, не намагайтеся розхитрити розробників, які підтримують ці пакети.Довіряйте розробникам. Фільтрування прапорів та їх заміна робляться для забезпечення стабільності системи та програми! Якщо ebuild-файл вказує на альтернативні прапори, то не намагайтеся це обійти.

Складання пакетів з неприпустимими прапорами швидше за все викличе проблеми. При створенні звіту про помилку на Bugzilla прапори, встановлені у файлі /etc/portage/make.conf, чітко видно, і розробники все одно попросять перезбирати пакет без цих прапорів. Щоб уникнути повторного складання, не використовуйте ці прапори спочатку. Не варто автоматично вважати себе більш обізнаним, ніж розробники.

Що з приводу LDFLAGS?

Розробники Gentoo вже встановили прості, безпечні LDFLAGS у базових профілях, тому не потрібно їх змінювати.

Чи можу я використати прапори для окремих пакетів?

Інформація про використання змінних середовища для кожного пакета окремо (включаючи CFLAGS) описана в настільній книзі Gentoo, "Змінне оточеннядля окремих пакетів".

Дивіться також

  • Налаштування параметрів компіляції (AMD64 Handbook)

Зовнішні ресурси

Наступні джерела можуть бути корисними для подальшого вивчення оптимізації: