Ветвь на ноль против производительности нулевого объекта - PullRequest
2 голосов
/ 30 сентября 2019

Что наиболее эффективно: использование нулевого объекта или ветвления в nullptr. Пример на C ++:

void (*callback)() = [](){}; // Could be a class member

void doDoStuff()
    {
    // Some code
    callback();  // Always OK. Defaults to nop
    // More code
    }

vs

void (*callback)() = nullptr; // Could be a class member

void doDoStuff()
    {
    // Some code
    if(callback != nullptr)  // Check if we should do something or not
        {callback();}
    // More code
    }

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

Повлияет ли замена обратного вызова на указатель на абстрактный базовый класс на решение?

Как насчет вероятности того, что callback будет установлен на что-то отличное от nullptr. Я предполагаю, что если callback, скорее всего, nullptr, то с дополнительной веткой это быстрее, верно?

Ответы [ 3 ]

3 голосов
/ 30 сентября 2019

Ни на один из этих вопросов нельзя ответить априори. Они будут зависеть от множества факторов, включая, помимо прочего, специфику аппаратного обеспечения, специфику кэша во время вызова, различный код такого вызова, который может скрыть любые введенные задержки, качествосила компиляции / девиртуализации компилятора (которая опять-таки зависит от конкретных деталей всего кода) и т. д.

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

2 голосов
/ 30 сентября 2019

Что наиболее эффективно: использование нулевого объекта или ветвления в nullptr.

Предполагая, что данное кодовое решение будет зависеть от вашей цели. И, если вы этого не предполагаете, это также будет зависеть от вашего кода, компилятора и, возможно, фазы луны.

Повлияет ли замена обратного вызова на указатель на абстрактный базовый класс?

В большинстве случаев это также будет динамическая диспетчеризация.

Как насчет вероятности того, что для обратного вызова установлено значение, отличное от nullptr. Я думаю, что если обратный вызов, скорее всего, nullptr, то он быстрее с дополнительной ветвью, верно?

Это будет зависеть от соотношения, а также от аппаратного обеспечения (является ли ветвь быстрее или не сравниваетсяк косвенному вызову функции, который также зависит от соотношения).


Просто чтобы вы знали, насколько тонки вещи: давайте предположим, что вы говорите о современных процессорах для настольных ПК x86_64, при этом вызов не является встроенными с вероятностью 99% времени nullptr. Люди сказали вам измерять.

Итак, вы сделали, и, в этом случае, давайте предположим, что вы обнаружили, что ветка кажется быстрее. Большой! Таким образом, мы должны начать использовать ветки везде, верно?

Не совсем, потому что ваш предиктор ветвления, вероятно, сделал код фактически свободным (ветвление никогда не выполнялось), что означает, что вы даже не сравнивали ветки с косвенными вызовами ввсе.

2 голосов
/ 30 сентября 2019

Вы должны протестировать код и выяснить,

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

Компиляторы очень хорошо оптимизируют код, особенно в отношении поведения, которое является предсказуемым, а ЦП часто создаются с помощью Branch. Прогнозирование или другие подобные технологии, которые уменьшают затраты на ветвление кода. Поэтому ответ зависит исключительно от конкретного варианта использования вашего кода, целевого устройства для вашего кода и условий, при которых он работает.

...