Страницы

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

суббота, 28 декабря 2019 г.

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

#c #указатели #производительность


Появился вопрос связанный с этим кодом, а конкретнее с функцией square. Когда у функции
скорость выполнения будет больше, с использованием указателей или без них? Я где-то
слышал или читал, что с указателями будет бытрее, потому что при их использовании не
создается дополнительная переменная, это так?

#include 

float square(float *number);

int main() {
    float number = 4.0;
    float second_number = square(&number);

    printf("Number two = %f\n", second_number);
    printf("Number = %f\n", number);

    getchar();
    return 0;
}

float square(float *number) {
    return *number * *number; 
}

    


Ответы

Ответ 1



Давайте для начала отставим cargo cult. Быстрее не потому, что «с указателями», быстрее потому, что эффективнее. Для того, чтобы понять, как будет эффективнее, вы должны понимать, что именно происходит и где именно теряется скорость. Без этого ваш вопрос похож на «будет ли еда вкуснее, если досыпать сахара?» В вашем случае при компиляции в release mode функция будет вшита в точку вызова и различий вовсе не будет. Компиляторы, поверьте, умеют оптимизировать гораздо лучше вас. Вы допускаете типичную ошибку новичка: пытаетесь оптимизировать (а) не разобравшись в том, как оно работает и почему, (б) в ущерб смыслу программы, (в) без предварительного профилирования. Не делайте так. Для вашего случая разница могла бы быть с плохим компилятором, который не умеет оптимизировать. Для этого случая у вас есть передача 32 бит float против передачи 32 или 64 бит указателя, плюс затраты на косвенный доступ. Прикидывайте сами. Но таких плохих компиляторов уже нет. Кроме того, разницу в несколько наносекунд вы вряд ли заметите, расходы на старт программы или ввод/вывод (и случайные флуктуации внутри них) на порядки больше. А уж коммуникация с пользователем замедляет всё ещё на несколько порядков.

Ответ 2



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

Ответ 3



Указатели (и в целом indirection - массивы, виртуальные функции и т. п.) плохо влияют на производительность по двум причинам: Дополнительные накладные расходы: чем больше вычислений нужно сделать, чтобы добраться до нужной переменной, тем больше времени уйдет на выполнение всей программы, особенно если к переменной обращаются внутри цикла. Это основная причина, по которой скриптовые языки вроде PHP, Python и Ruby такие медленные - там невозможно убрать лишнюю индерекцию внутри критического цикла, не переписав что-то на C Увеличение числа cache misses - современные процессоры полагаются на иерархическую память, каждый уровень которой больше и медлительнее (В Windows и Linux на процессорах Intel примерная схема: регистры -> кэш 1 уровня -> кэш 2 уровня -> кэш 3 уровня -> оперативная память -> swap, но все что ниже оперативы в общем зависит от ОС, например OS X добавляет между ней и свапом сжатую память). Время, нужное на "всплытие" переменной по иерархии - главный источник простаивания процессора и главный бич производительности после неоптимальных алгоритмов. Поэтому лишние указатели - зло. В данном случае вы передаете в функцию 8-байтовый указатель вместо 4-байтового float-а, что ничем не оправдано. Не цитируйте меня, но ЕМНИП в современных системах стоит передавать переменные по значению, только когда их размер не больше 32 байт. Еще одна менее очевидная проблема с передачей параметров по указателю - вызывающий код не может гарантировать, что функция не перезапишет данные в соответствующих переменных. Иногда это желаемое поведение (например, в scanf), но чаще это только плодит ошибки и создает проблемы оптимизатору в компиляторе. В каком случае использование указателей оправдано? Когда иначе вы бы копировали слишком много данных или не могли использовать хороший алгоритм. Это довольно размытое правило, потому что это довольно сложная тема. В конце концов вопросы производительности решают, сравнивая варианты реализации на практике.

Ответ 4



Я где-то слышал или читал, что с указателями будет быстрее, потому что при их использовании не создается дополнительная переменная, это так? Коротко – да, но не в данном случае. В вашей функции вы передаете указатель на float. Размер float 4 байта, размер указателя минимум 4 байта, так что разницы в принципе никакой. Указатели передают как аргумент функции, если нужно оперировать именно с указанным участком памяти, или если размер аргумента очень велик (очень утрировано и примитивно на самом деле, но суть должна быть ясна).

Ответ 5



Вообще вопрос не о том :) Указатели нужны там, где они действительно нужны. О производительности на вашем уровне говорить пока очень рано. Не разобравшись как следует с самим языком, с алгоритмической базой, эффективными структурами данных, и прочим, и нечего думать в этом направлении. А, нужно ещё освоить дебагер и профайлер, да :) Вот тогда и можно будет вернуться к вопросу.

Ответ 6



Да это так, но лучше не использовать указатели где попало, а только в крайних случаях. Ошибки с указателями очень тяжело отслеживаются, и для работы с указателями требуются определенные навыки. В книге "Совершенный код (2 издание)" рекомендуют использовать поменьше указателей если нет в них острой необходимости

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

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