Несколько лет назад я изучал ассемблер x86, конвейер процессора, пропуски кэша, предсказание ветвей и весь этот джаз.
Это была сказка о двух половинах. Я прочитал обо всех замечательных преимуществах длинных конвейеров в процессоре, таких как переупорядочение команд, предварительная загрузка кеша, чередование зависимостей и т.д.
Недостатком было то, что любое отклонение нормы было чрезвычайно дорогостоящим. Например, IIRC для некоторых процессоров AMD в эпоху раннего гигагерца был 40 циклов каждый раз, когда вы вызывали функцию через указатель (!), И это было, по-видимому, нормальным.
Это не пренебрежимо малое число "не беспокойтесь об этом"! Имейте в виду, что "хороший дизайн" обычно означает "как можно больший фактор" и "кодировать семантику в типы данных", которые часто подразумевают виртуальные интерфейсы.
Компромисс заключается в том, что код, который не выполняет такие операции, может получить более двух инструкций за цикл. Это номера, о которых хочется беспокоиться при написании высокопроизводительного кода на С++, который тяжел для дизайна объекта и освещает количество хрустов.
Я понимаю, что тенденция длинного CPU-конвейера изменилась, когда мы вступаем в эпоху малой мощности. Вот мой вопрос:
Поддерживает ли последнее поколение x86-совместимых процессоров массивные штрафы за вызовы виртуальных функций, предсказания плохих ветвей и т.д.