AI-приложения в C ++: Насколько дороги виртуальные функции? Каковы возможные оптимизации? - PullRequest
16 голосов
/ 01 октября 2008

В приложении AI я пишу на C ++,

  1. не так много численных расчетов
  2. существует множество структур, для которых необходим полиморфизм во время выполнения
  3. очень часто некоторые полиморфные структуры взаимодействуют во время вычислений

Есть ли в такой ситуации какие-либо методы оптимизации? Хотя сейчас я не буду заботиться об оптимизации приложения, одним из аспектов выбора C ++ вместо Java для проекта было предоставление большего рычага для оптимизации и возможность использования не объектно-ориентированных методов (шаблоны, процедуры, перегрузка).

В частности, какие методы оптимизации связаны с виртуальными функциями? Виртуальные функции реализуются через виртуальные таблицы в памяти. Есть ли какой-нибудь способ предварительно извлечь эти виртуальные таблицы в кэш L2 (стоимость выборки из памяти / кэш L2 увеличивается)?

Помимо этого, есть ли хорошие ссылки на методы локальности данных в C ++? Эти методы позволят сократить время ожидания выборки данных в кэш L2, необходимое для вычислений.

Обновление : Также см. Следующие связанные форумы: Штраф за производительность интерфейса , Несколько уровней базовых классов

Ответы [ 15 ]

2 голосов
/ 01 октября 2008

Вы можете реализовать полиморфизм во время выполнения, используя виртуальные функции, и во время компиляции, используя шаблоны. Вы можете заменить виртуальные функции шаблонами. Посмотрите на эту статью для получения дополнительной информации - http://www.codeproject.com/KB/cpp/SimulationofVirtualFunc.aspx

1 голос
/ 16 марта 2009

С современными, ориентированными на будущее, несколькими диспетчерскими процессорами издержки на виртуальную функцию вполне могут быть равны нулю. Нада. Zip.

1 голос
/ 17 октября 2008

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

1 голос
/ 01 октября 2008

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

Кэш, как правило, возникает только при работе с большими структурами данных, которые:

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

Такие вещи, как Vtables, обычно не будут проблемой производительности / кэша / памяти; обычно существует только один Vtable для каждого типа объекта, и объект содержит указатель на Vtable вместо самой Vtable. Так что, если у вас нет нескольких тысяч типов объектов, я не думаю, что Vtables разрушит ваш кеш.

1), кстати, именно поэтому такие функции, как memcpy, используют обходные кеш-команды потоковой передачи, такие как movnt (dq | q), для очень больших (многомегабайтных) входных данных.

0 голосов
/ 01 октября 2008

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

Для виртуальных функций доступно несколько оптимизаций,

  1. Люди написали компиляторы, которые прибегают к анализу кода и преобразованию программы. Но это не компиляторы промышленного уровня.
  2. Вы можете заменить все виртуальные функции эквивалентными блоками «switch ... case» для вызова соответствующих функций в зависимости от типа в иерархии. Таким образом, вы избавитесь от виртуальной таблицы, управляемой компилятором, и получите собственную виртуальную таблицу в виде блока switch ... case. Теперь шансы на то, что ваша собственная виртуальная таблица окажется в кеше L2, высоки, как и в пути кода. Помните, что для этого вам понадобится RTTI или ваша собственная функция typeof.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...