gcc маловероятно использование макроса

Я пишу критический кусок кода с примерно следующей логикой

if(expression is true){
   //do something with extremely low latency before the nuke blows up. This branch is entered rarely, but it is the most important case
}else{
   //do unimportant thing that doesnt really matter
}

Я собираюсь использовать макрос вероятности () вокруг выражения, поэтому, когда он попадает в важную ветвь, я получаю минимальную задержку. Мой вопрос заключается в том, что использование действительно противоположно предложенному названию макроса, потому что я выбираю "маловероятную" ветвь для предварительной выборки. Есть ли явный недостаток в этом с точки зрения производительности?

2 ответа

Да. Вы обманываете компилятор, помечая ветвь маловероятно, но должна быть быстрой, как если бы это была вероятная ветвь, в надежде, что компилятор сделает это быстрее.

В этом есть явный недостаток - если вы не напишите хороший комментарий, объясняющий, что вы делаете и почему, какой-то сопровождающий (возможно, вы сами) через шесть месяцев почти гарантированно скажут: "Эй, похоже, он положи скорее всего не ту ветку "и" исправь ".

Существует также гораздо менее вероятный, но все же возможный недостаток, что некоторые версии некоторых компиляторов, которые вы используете сейчас или в будущем, будут делать разные вещи, чем вы ожидаете с вероятным макросом, и эти разные вещи будут не такими, как вы хотели чтобы заставить компилятор сделать это, вы получите код, который каждый раз в цикле тратит $100K спекулятивно, проходя 90% пути до остановки реактора перед его отменой.

Это абсолютно противоположно традиционному использованию __builtin_expect(x, 1), который используется в смысле макроса:

#define likely(x) __builtin_expect(x, 1)

что я лично считаю плохой формой (поскольку вы загадочно помечаете маловероятный путь как вероятный выигрыш в производительности). Тем не менее, вы все еще можете отметить эту оптимизацию, так как __builtin_expect(x) не делает никаких предположений о ваших потребностях, заявляя путь "похоже" - это просто стандартное использование. Чтобы делать то, что вы хотите, я бы предложил:

#define optimize_path(x) __builtin_expect(x, 1)

который будет делать то же самое, но вместо того, чтобы заставлять код обвинять маловероятный путь в вероятности, теперь вы заставляете код описывать то, что вы действительно пытаетесь - оптимизировать критический путь.

Тем не менее, я должен сказать, что если вы планируете синхронизировать ядерное оружие - вы должны не только вручную проверять (и синхронизировать) скомпилированную сборку, чтобы обеспечить правильную синхронизацию, но вы также должны использовать RTOS. Неправильное предсказание ветвления будет иметь чрезвычайно незначительный эффект, так что здесь оно почти не нужно, поскольку вы можете компенсировать событие "1 на миллион", просто имея более быстрый процессор или правильно рассчитав задержку для ошибочного прогноза. Что влияет на время современных компьютеров, так это выгрузка и планирование ОС. Если вам нужно, чтобы что-то происходило в очень дискретном масштабе времени, вы должны планировать их в реальном времени, а не в псевдо-реальном времени, что есть в большинстве операционных систем общего назначения. Неправильное предсказание ветвления обычно в сотни раз меньше, чем задержка, которая может возникнуть из-за неиспользования RTOS в ситуации RT. Как правило, если вы полагаете, что неправильное прогнозирование ветвления может быть проблемой, вы удаляете ветвь из чувствительной ко времени проблемы, так как предиктор ветвления обычно имеет сложное состояние и находится вне вашего контроля. Макросы, такие как "вероятный" и "маловероятный", предназначены для блоков кода, которые могут попадать из разных областей, с различными состояниями предсказания ветвлений и, что наиболее важно, используются очень часто. Высокая частота попадания в эти ветви приводит к ощутимому увеличению производительности для приложений, которые его используют (например, ядро ​​Linux). Если вы нажмете на ветку только один раз, вы можете получить повышение производительности на 1 наносекунду в некоторых случаях, но если приложение когда-либо критично к этому времени, есть другие вещи, которые вы можете сделать, чтобы помочь себе значительно увеличить производительность.

Другие вопросы по тегам