Скільки використання "ймовірних" та "малоймовірних" макросів занадто багато?


12

Часто відомі як макроси likelyі unlikelyмакроси допомагають компілятору дізнатися, чи ifбуде звичайно вводитись або пропускати. Використання його призводить до деяких (досить незначних) поліпшень продуктивності.

Я почав їх використовувати нещодавно, і не знаю, як часто такі підказки слід використовувати. Зараз я використовую його для перевірки помилок if, які зазвичай позначаються як unlikely. Наприклад:

mem = malloc(size);
if (unlikely(mem == NULL))
  goto exit_no_mem;

Це здається нормальним, але перевірка помилок ifтрапляється досить часто і, отже, використання вказаних макросів.

Моє запитання: чи занадто багато макросів likelyі unlikelyмакросів для кожної перевірки помилок if?

Хоча ми ще в цьому, які інші місця вони часто використовують?


У моєму теперішньому використанні це бібліотека, яка робить абстракцію від підсистеми в режимі реального часу, тому програми стануть переносними між RTAI, QNX та іншими. Однак, більшість функцій є досить маленькими і безпосередньо викликають одну-дві інші функції. Багато навіть static inlineфункцій.

Отже, по-перше, це не програма, яку я міг би профілювати. Немає сенсу "визначати шийки", оскільки це бібліотека, а не окрема програма.

По-друге, це на кшталт "я знаю, що це малоймовірно, я б також міг сказати це компілятору". Я активно не намагаюся оптимізувати це if.


7
reeks мікро-оптимізації для мене ...
храповик урод

2
Щодо коду програми, я додав би їх лише у тому випадку, якщо профілювання показало, що цей код використовується гарячим шляхом.
CodesInChaos


@james, це просто говорить likelyі unlikelyіснує, і що вони роблять. Я не знайшов нічого, що б насправді підказувало, коли і де найкраще їх використовувати.
Шахбаз

@Shahbaz "Якщо умова часто хибна, виконання не є лінійним. У середині є великий шматок невикористаного коду, який не тільки забруднює L1i за рахунок попереднього вибору, але й може спричинити проблеми з передбаченням гілок. Якщо галузеве передбачення неправильне, умовне вираження може бути дуже неефективним ". Отже, щільні петлі, де ви хочете переконатися, що потрібні вам інструкції знаходяться в кеші L1i
Джеймс

Відповіді:


12

Чи потрібна вам така продуктивність, що ви готові забруднити свій код цим? Це незначна оптимізація.

  • Чи працює код у тісному циклі?
  • Чи є у вашої програми проблеми з роботою?
  • Ви профілювали свою програму і визначили, що цей цикл коштує багато часу на процесорі?

Якщо ви не зможете відповісти yesна все вищезазначене, не переймайтеся подібними речами.

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


1
Щоб було зрозуміло, я вас не проголосував. Однак ваша відповідь насправді не відповідає на моє запитання. Ви намагаєтесь сказати, що (un)likelyмакрос використовується рідко і лише в надзвичайно критичному коді? Це "погана практика" використовувати його часто, або просто "непотрібно"?
Шахбаз

@Shahbaz Це робить код менш читабельним і оптимізація продуктивності може коливатися від тривіального посилення до тривіальної втрати. Останнє, коли припущення про ймовірність було або неправильним, або було змінено на неправильне через пізніші зміни в інших частинах коду. Якщо ніколи не слід використовувати, якщо не потрібно.
Пітер

3
@Peter: Хоча це занадто погано, синтаксис не приємніший, нотації про те, що є ймовірним чи малоймовірним, може надавати корисну інформацію людям, які читають код. Наприклад, хтось, хто бачив if (likely(x==2 || x==3)) doOneThing(); else switch(x) { ... }, може судити про те, що використання програміста ifдля значень 2 і 3 не було лише наслідком того, що програміст не знає, що C може асоціювати дві caseмітки з одним обробником.
supercat

Ніхто не згадав, що я вважаю критичним моментом. Справа не лише в тому, що "малоймовірний" шлях трапляється рідше, це може бути і те, що обумовлений на цьому шляху, який ви не переймаєте швидкістю. Наприклад, периферійний пристрій стає невідповідним, тому вам доведеться скинути його і спати в будь-якому випадку.
Бенджамін Ліндквіст

2

Якщо ви пишете для x86 / x64 (і не використовуєте 20-річні процесори), приріст продуктивності від використання __builtin_expect () буде незначним, якщо такий є. Причиною цього є те, що сучасні процесори x86 / x64 (але не на 100% впевнені в Atom) мають динамічне прогнозування гілок, тому по суті процесор «дізнається» про гілку, яка береться частіше. Звичайно, ця інформація може зберігатися лише для обмеженої кількості відділень, однак можливі лише два випадки. Якщо (a) це "часто використовувана" гілка, то ваша програма отримає користь від цього динамічного прогнозування гілки, і якщо (b) це "рідкісна" гілка, ви дійсно не побачите жодного реалістичного показника ефективності через неправильні прогнози в такі рідкісні гілки (20 циклів процесора неправильного прогнозування не є поганими, якщо це трапляється один раз у синій місяць).

Зверніть увагу: це НЕ означає, що в сучасних x86 / x64 важливість неправильного прогнозування гілок знизилася: будь-яка гілка з 50-50 шансом стрибку-непідкопувача все ще зазнає штрафу (IIRC 10-20 циклів процесора), тому у внутрішніх петлях гілки можуть все-таки потрібно уникати. Важливим є лише __builtin_expect () на x86 / x64, який зменшився (IIRC, близько 10-15 років тому або близько того) - головним чином через динамічне прогнозування гілок.

NB2: для інших платформ поза x86 / x64, YMMV.


Ну, компілятор знає, на яку галузь процесор очікує менш ймовірність. І це може домовитись, що це насправді малоймовірно. Але компілятор, ймовірно, вже знає цей шаблон без unlikelyпримітки.
Дедуплікатор

@Deduplicator: при динамічному прогнозуванні гілок компілятор не знає, яка гілка є більшою ймовірністю, оскільки ЦП обчислює її під час виконання на основі попередніх пробіжок через цю саму точку коду.
Заєць без клопів
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.