Что является хорошим примером использования переменной регистра в C? - PullRequest
31 голосов
/ 24 ноября 2008

Я читаю K & R и зашел в небольшой раздел о переменных регистра, и мне было интересно, есть ли у людей здесь хорошие примеры этого применения на практике.

Из раздела 4.7 в K & R:

Объявление регистра выглядит как
зарегистрируйте int x;
зарегистрировать символ c;

Чтобы было ясно, я просто надеюсь увидеть несколько классных примеров кода. Я (почти уверен, что я) понимаю предмет, поэтому не чувствую необходимости вводить подробное объяснение (если вы этого не хотите).

Ответы [ 6 ]

68 голосов
/ 24 ноября 2008

Нет хорошего примера использования регистра при использовании современных компиляторов (читай: последние 15 с лишним лет), потому что он почти никогда не приносит пользы и может приносить вред. Когда вы используете register, вы говорите компилятору: «Я знаю, как оптимизировать мой код лучше, чем вы», что почти никогда не происходит. При использовании регистра может произойти одно из трех:

  • Компилятор игнорирует это, это наиболее вероятно. В этом случае единственный вред состоит в том, что вы не можете взять адрес переменной в коде.
  • Компилятор учитывает ваш запрос, и в результате код работает медленнее.
  • Компилятор обрабатывает ваш запрос, и код выполняется быстрее, это наименее вероятный сценарий.

Даже если один компилятор создает лучший код при использовании регистра, нет никаких оснований полагать, что другой будет делать то же самое. Если у вас есть какой-то критический код, который компилятор недостаточно хорошо оптимизирует, лучше всего в любом случае, вероятно, использовать ассемблер для этой части, но, конечно, сначала выполните соответствующее профилирование, чтобы убедиться, что сгенерированный код действительно является проблемой.

12 голосов
/ 24 ноября 2008

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

Но в 99% случаев объяснение Робертса также хорошо для встроенного слова.

4 голосов
/ 15 июня 2013

Я знаю, что это довольно давно, но здесь есть реализация подпроцедуры из heapsort, в которой использование переменных реестра ускоряет алгоритм, по крайней мере, с помощью gcc 4.5.2 для компиляции кода

inline  void max_heapify(int *H, int i){
    char OK = FALSE;
    register int l, r, max, hI;
    while(!OK){
        OK = TRUE;
        l = left(i);
        r = right(i);
        max = i;
        if(l <= H[SIZE] && H[l] > H[i]){
            max = l;
        }
        if(r <= H[SIZE] && H[r] > H[max]){
            max = r;
        }
        if(max != i){
            OK = FALSE;
            hI = H[i];
            H[i] = H[max];
            H[max] = hI;
            i = max;
        }
    }
}

Я протестировал алгоритм с и без ключевого слова register перед атрибутами и выполнил его, чтобы отсортировать случайный массив с 50 000 000 элементов в моей записной книжке, несколько раз для каждой версии.

использование регистров сократило время сортировки с ~ 135 с до ~ 125 с.

Я также протестировал только 5 000 000 элементов, но выполнил его несколько раз.

Версия без регистра начиналась в 11 с, но каждое исполнение уменьшало время до 9,65 с и останавливалось на этом

версия с регистром началась в 10 секунд и снизила время до 8,80 секунд.

Я думаю, это как-то связано с кеш-памятью. Тем не менее, кажется, что регистры ускоряют алгоритм благодаря постоянному коэффициенту

Поскольку эти переменные довольно часто используются в алгоритме, то, гарантируя, что они находятся в регистре, вместо того, чтобы оставлять эту работу компилятору, в этом случае был достигнут лучший результат. Однако это не сильно улучшило время.

Надеюсь, это кому-нибудь пригодится, привет.

3 голосов
/ 14 декабря 2008

Другой распространенный случай - реализация низкоуровневых интерпретаторов. Сохранение некоторого состояния в регистрах, например. указатель стека виртуальной машины, может значительно уменьшить доступ к памяти и ускорить ваш код.

См. vmgen - генератор эффективных интерпретаторов виртуальных машин для примера оптимизации (5.2 Кэширование вершины стека).

1 голос
/ 05 января 2013

во-первых, переменная регистра должна использоваться для часто используемых переменных, таких как переменная управления циклом, для повышения производительности за счет минимизации времени доступа. вторичный вы можете использовать только и только зарегистрировать спецификатор хранилища в этой ситуации как, веселье (auto int a, auto int b): ошибка Приколы (зарегистрируйте int a, зарегистрируйте int b): правильно, только это будет выполнено fun (static int a, static int b): ошибка fun (extern int a, extern int b): ошибка

0 голосов
/ 21 октября 2018

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

Причиной использования сборки вместо C является исключительно из-за проблем с производительностью, возникающих во время разработки, так что да, существует необходимость в ключевом слове register, но во многих случаях оно не работает, как задумано разработчиком

...