ТЕХНИКА ОПТИМИЗАЦИИ ПРОГРАММ

       

Оптимизация передачи аргументов


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

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

Компилятор Microsoft Visual C++ отводит для передачи аргументов два регистра, Borland C++ - три, а WATCOM – четыре. Вопрос: "чья стратегия лучше?" остается открыт и единого мнения нет. Автор этой статьи склоняется к мысли, что два регистра – действительно, наилучший компромисс. К слову сказать, Microsoft C 7.0 – "прародитель" Microsoft Visual C++ – использовал для передачи аргументов три регистра, но после серии испытаний, осуждений, споров и дебатов, его разработчики пришли к выводу, что два регистра обеспечивают лучшую производительность, нежели три.

Другой важный момент – тип вызова функции по умолчанию. Компилятор Microsoft Visual C++ задействует регистровую передачу аргументов только в том случае, если перед функцией указан квалификатор __fastcall (исключение составляет неявный аргумент this по умолчанию передаваемый через регистр). Компиляторы же Borland C++ и WATCOM по умолчанию используют регистровую передачу аргументов. Поэтому, если вы используете Microsoft Visual C++, вставляйте квалификатор __fastcall самостоятельно.



Содержание раздела