Страницы

Поиск по вопросам

четверг, 19 декабря 2019 г.

Указатель на функцию и производительность

#cpp


void foo(){}
//...
void (*fptr)() = foo;


Влияет ли использование указателя на функцию на производительность? (как?)
    


Ответы

Ответ 1



Одиночный вызов через указатель может негативно влиять на производительность просто потому, что целевой адрес необходимо читать из памяти данных, т.е. он не содержится непосредственно в потоке команд. Одиночный вызов через указатель может негативно влиять на производительность потому, что косвенная передача управления затрудняет предсказание переходов и поэтому может подавлять конвейерную обработку команд в современных суперскалярных процессорах. Если конкретная машинная архитектура не занимается предсказанием переходов и суперскалярной обработкой команд, то этот недостаток на таких архитектурах не будет иметь места. Множественный вызов через указатель на один и тот же адрес (напр. в цикле) может НЕ привести к ухудшению производительности потому, что чтение целевого адреса из памяти (в регистр процессора) может быть выполнено один раз заранее (пункт 1) и тривиальный подход к предсказанию косвенных переходов дает правильный результат (пункт 2). Разумеется, предварительное "кэширование" целевого адреса на уровне сгенерированного компилятором кода возможно только в том случае, если компилятор уверен в том, что адрес остается неизменным от вызова к вызову.

Ответ 2



Здесь скорее более уместно говорить о том будет ли сгенерирован одинаковый машинный код для прямого вызова функции и вызова функции по указателю. И, если машинный код будет одинаковый, то и производительность никак не изменится вне зависимости от архитектуры процессора. В данном случае за все отвечает транслятор языка. И, конечно, без оптимизации скорее всего вызов по указателю будет содержать дополнительное действие. Но, при малейшей оптимизации, эти вызовы уже станут одинаковыми. Мало того, при небольшом объеме функции ее тело вообще может быть вставлено в код. В конечном итоге сложно сказать какой код сгенерирует транслятор языка, все зависит от самого транслятора и его опций оптимизации. Но практика показывает, что большинство трансляторов, даже довольно давних, хорошо оптимизирует код. Например следующий код (gcc 8.2 -O3): int main() { int (*f)() = func; func(); f(); return 0; } будет транслирован в: main: sub rsp, 8 call func() call func() xor eax, eax add rsp, 8 ret Как видно вызов функций одинаков. Можете перейти по ссылке выше и поэксперементировать с разными компиляторами и опциями оптимизации. А, отвечая на вопрос, то, при даже небольшой оптимизации, подавляющее большинство трансляторов сгенерируют код при котором использование указателя на функцию никак не повлияет на производительность.

Комментариев нет:

Отправить комментарий