Какой хороший пример использования регистровой переменной в C?

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

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

The register declaration looks like
register int x;
register char c;

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
36
0
30 052
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

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

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

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

«Три вещи могут случиться, а две - плохо»? Где я такое слышал раньше ... ;-)

Steve Jessop 25.11.2008 06:13

Помните, что компилятор совершенно свободен проигнорировать ваше предложение - в стандарте нет ничего, что говорило бы, что он должен помещать регистровую переменную в регистр.

Martin Beckett 14.12.2008 01:09

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

Johannes Schaub - litb 14.12.2008 01:51

хотя в этом случае __attribute __ ((register_function)) или тому подобное было бы лучше, я думаю

Johannes Schaub - litb 14.12.2008 03:01

Этот ответ оказал большое влияние. Подавляющее большинство объявлений регистров было удалено из кода Perl., со ссылкой на этот ответ.

Palec 11.08.2014 17:51

Этот ответ вводит в заблуждение. Ключевое слово register касается не аппаратных регистров, а оптимизации. Единственный его эффект состоит в том, что адрес такой переменной не может быть получен. В частности, его можно использовать для создания псевдонимов переменных, что может быть весьма полезно.

Jens Gustedt 24.07.2015 13:09

Это не вводит в заблуждение, это совершенно неправильно. Соответствующий компилятор не могу игнорирует register: получение адреса переменной недопустимо, он не может это игнорировать. Это единственное, что делает ключевое слово: генерирует дополнительные проверки и ошибки, чтобы помочь люди.

Leushenko 30.08.2015 21:57

@Leushenko: Интересно, было бы полезно иметь типы "указатель на значение с указанием регистра", чтобы void foo(int register *p); гарантировал, что p не будет сохраняться после вызова функции, а int scanf(char const *fmt, register ...) будет гарантировать, что указатели не будут переданы как переменные аргументы будет сохраняться. Тогда компилятор может сделать register int i; scanf("%d", &i); эквивалентом register int i; int temp; scanf("%d", &temp); i=temp;, но ему будет разрешено опускать временный интервал, когда он ему не нужен.

supercat 28.01.2016 20:42

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

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

Честно говоря, это очень похоже на то, что сказал Роберт.

Jonathan Leffler 24.11.2008 22:22

Вообще-то ты вроде и прав. Я перечитал сообщение, и последний абзац разъясняет то, что я хотел уточнить ... В следующий раз я буду читать получше

Ilya 24.11.2008 23:02

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

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

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

Какие?! Текст K&R относится к 1970-м годам, поэтому некоторые из их рекомендаций немного устарели. Использование register, безусловно, одно из таких.

Bo Persson 05.01.2013 16:43

Я знаю, что это довольно давно, но вот реализация подпроцедуры из 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 с.

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

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

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

Чтобы серьезно относиться к тестированию, вы должны предоставить информацию о том, как вы его скомпилировали (какие флаги), на какой платформе вы это сделали, и, возможно, некоторые подробности о вашей архитектуре и / или процессоре. Также важно, как вы запускали max_heapify.

raylu 02.07.2014 11:13

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

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

Другие вопросы по теме