Техника оптимизации под линуха

       

Распределение переменных по регистрам


Регистров общего назначения всего семь, а чаще и того меньше. Регистр EBP используется для организации фреймов (так же называемых стековыми кадрами), регистр EAX по общепринятому соглашению используется для возращения значения функции. Некоторые команды (строковые операции, умножение/деление) работают с фиксированным набором регистров, который на протяжении всей функции приходился держать "под сукном" или постоянно гонять данные от одного регистра к другому, что так же не добавляет производительности.

Стратегия оптимального распределения переменных по регистрам (global registers allocation)— сложная задача, которую еще предстоит решить. Пусть слово "global" не вводит вас в заблуждение. Эта глобальность сугубо локального масштаба, ограниченная одной-единственной функцией, а то и ее частью.

Компиляторы стремятся помещать в регистры наиболее интенсивно используемые переменные, однако, под "интенсивностью" здесь понимается отнюдь не частота использования, а количество "упоминаний". Но ведь не все "упоминания" равнозначны! Вот, например, if (++a % 16) b++; else c++;

обращение к переменной c происходит в 16 раз чаще! Статистка обращений не всегда может быть получена путем прямого анализа исходного кода программы, так что ждать помощи со стороны машины — наивно.

Языки Си/Си++ поддерживают специальное ключевое слово "register", управляющее размещением переменных, однако, оно носит характер рекомендации, а не императива и все три рассматриваемых компилятора его игнорируют, предпочитая интеллекту программиста свой собственный машинный интеллект.

Представляет интерес сравнить распределение переменных по регистрам в глубоко вложенных циклах, поскольку его вклад в общую производительность весьма значителен. Рассмотрим следующий пример:

int *a, *b;

main(int n, char **v)

{

       int i,j; int sum=0;

       for (i = 0; i < n; i++)

              for (j = 0; j < n; j++)

                     sum += sum*a[n*i + j] + sum/b[j] + x++;

       return sum+x;

}



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