Виртуальные функции и производительность - C++

117
задан Scott Stensland 13 January 2016 в 17:47
поделиться

10 ответов

Хорошее эмпирическое правило:

Это не проблема производительности, пока Вы не можете доказать его.

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

превосходная статья, которая говорит о виртуальных функциях (и больше) Указатели Функции членства и Самые Быстрые Делегаты C++ .

86
ответ дан Greg Hewgill 24 November 2019 в 02:00
поделиться

Потеря производительности использования виртуальных функций никогда не может перевешивать преимущества, Вы достигаете уровень дизайна. Предположительно, вызов к виртуальной функции был бы на 25% менее эффективным тогда прямой вызов статической функции. Это вызвано тем, что существует уровень абстракции через VMT. Однако время, потраченное для совершения вызова, является обычно очень маленьким по сравнению со временем, потраченным в фактическом выполнении функции, таким образом, общая стоимость производительности будет nigligable, особенно с текущей производительностью аппаратных средств. Кроме того, компилятор может иногда оптимизировать и видеть, что никакой виртуальный вызов не необходим, и скомпилируйте его в статический вызов. Не волнуйте виртуальные функции использования и абстрактные классы так, как Вам нужно.

0
ответ дан 24 November 2019 в 02:00
поделиться

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

, Хотя как другие люди сказали, что это в значительной степени никогда не будет проблемой для Вас в реальной жизни. И если Вы думаете, что это - выполняет профилировщика, сделайте некоторые тесты и проверьте - ли это действительно проблема прежде, чем попытаться "не разработать" Ваш код для выигрыша в производительности.

3
ответ дан Daemin 24 November 2019 в 02:00
поделиться

Существует другая производительность критерии помимо времени выполнения. Vtable поднимает пространство памяти также, и в некоторых случаях может избежаться: ATL использует время компиляции" моделируемое динамическое связывание " с шаблоны для получения эффекта "статического полиморфизма", который является видом трудно для объяснения; Вы в основном передаете производный класс в качестве параметра шаблону базового класса, таким образом, во время компиляции базовый класс "знает" то, что его производный класс находится в каждом экземпляре. Не позволит Вам сохранить несколько различных производных классов в наборе базовых типов (это - полиморфизм во время выполнения), но от статического смысла, если Вы хотите сделать класс Y, который совпадает с существующим ранее шаблонным классом X, который имеет рычаги для этого вида переопределения, просто необходимо переопределить методы, о которых Вы заботитесь, и затем Вы получаете базовые методы класса X, не имея необходимость иметь vtable.

В классах с местами памяти большой емкости, стоимость единственного vtable указателя не очень, но некоторые классы ATL в COM являются очень маленькими, и это стоит vtable сбережений, если случай полиморфизма во время выполнения никогда не собирается происходить.

См. также это другой ТАК вопрос .

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

6
ответ дан Community 24 November 2019 в 02:00
поделиться

От страницы 44 "Оптимизация Вуали Agner программного обеспечения в C++" руководство :

время это берет для вызова, виртуальная функция членства является несколькими тактами больше, чем это берет для вызова невиртуальной функции членства, при условии, что оператор вызова функции всегда называет ту же версию виртуальной функции. Если изменения версии тогда Вы получите misprediction штраф 10 - 30 тактов. Правила для прогноза и misprediction вызовов виртуальной функции совпадают с для операторов переключения...

28
ответ дан Boojum 24 November 2019 в 02:00
поделиться

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

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

вызов виртуальной функции А сначала должен загрузить vtable указатель из объекта. Это может привести к неудачному обращению в кэш данных. Тогда это загружает указатель функции из vtable, которое может привести к другому неудачному обращению в кэш данных. Тогда это вызывает функцию, которая может привести к неудачному обращению в кэш инструкции как невиртуальная функция.

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

34
ответ дан Mark James 24 November 2019 в 02:00
поделиться

абсолютно. Это была проблема путь назад, когда компьютеры достигли 100 МГц, поскольку каждый вызов метода потребовал поиска на vtable, прежде чем это назвали. Но сегодня.. на ЦП на 3 ГГц, который имеет 1-й кэш уровня с большей памятью, чем мой первый компьютер, имел? Нисколько. Выделение памяти от основной RAM будет стоить Вам большего количества времени, чем если бы все Ваши функции были виртуальными.

как старые, былые времена, где люди сказали структурное программирование, был медленным, потому что весь код был разделен на функции, каждая функция требуемые выделения стека и вызов функции!

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

пз думают о других 'простых в использовании' языках - все их методы являются виртуальными под покрытиями, и они не проверяют в наше время.

7
ответ дан gbjbaanb 24 November 2019 в 02:00
поделиться

Когда Objective C (где все методы являются виртуальными) является основным языком для iPhone и чертовски' , Java является основным языком для Android, я думаю, что довольно безопасно использовать виртуальные функции C++ на наших двухъядерных башнях на 3 ГГц.

42
ответ дан Chuck 24 November 2019 в 02:00
поделиться

Ваш вопрос сделал меня любопытным, таким образом, я шел вперед и выполнил некоторые синхронизации на 3 ГГц, чтобы ЦП PowerPC мы работаем с. Тест, который я запустил, должен был сделать простое 4d, векторный класс с добирается/функции множества

class TestVec 
{
    float x,y,z,w; 
public:
    float GetX() { return x; }
    float SetX(float to) { return x=to; }  // and so on for the other three 
}

Тогда, я настроил три массива каждый содержащий 1024 из этих векторов (достаточно маленький для помещений в L1) и выполнил цикл, который добавил их друг к другу (A.x = B.x + C.x) 1000 раз. Я выполнил это с функциями, определяемыми как inline, virtual, и вызовы регулярной функции. Вот результаты:

  • встроенный: 8 мс (0,65 нс за вызов)
  • прямой: 68 мс (5,53 нс за вызов)
  • виртуальный: 160 мс (13 нс за вызов)

Так, в этом случае (где все помещается в кэш) вызовы виртуальной функции были о 20x медленнее, чем встроенные вызовы. Но что это действительно означает? Каждое прохождение через цикл вызвало точно 3 * 4 * 1024 = 12,288 вызовы функции (1024 раза векторов четыре раза компонентов, три вызова на добавляют), таким образом, эти времена представляют 1000 * 12,288 = 12,288,000 вызовы функции. Виртуальный цикл взял на 92 мс дольше, чем прямой цикл, таким образом, дополнительные издержки на вызов равнялись 7 наносекунды на функцию.

От этого я завершаю: да , виртуальные функции намного медленнее, чем прямые функции, и никакой , если Вы не планирование вызова их десять миллионов раз в секунду, это не имеет значения.

См. также: сравнение сгенерированного блока.

163
ответ дан Crashworks 24 November 2019 в 02:00
поделиться

Да, Вы правы и если Вы любопытный на предмет стоимости вызова виртуальной функции Вы могли бы найти это сообщение интересный.

4
ответ дан Serge 24 November 2019 в 02:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: