когда использовать регистры в C?
-
20-09-2019 - |
Вопрос
у меня есть что-то вроде этого
register unsigned int a, b, c;
int n;
for (n = 0; n < 10; ++n){
c = a + b
b = a
a = c
array[n] = c;
}
что он делает, не имеет значения.Код работает быстро, как сейчас, медленнее, если удалить ключевое слово Register.Однако когда я добавляю регистр перед int n, он фактически работает медленнее, чем сейчас, но быстрее, чем если бы регистры не использовались.
Может кто-то объяснить это мне?Спасибо.
Решение
register
дает компилятору подсказку о необходимости поместить переменную в регистр вместо памяти/стека.В некоторых случаях для каждой переменной, в которую вы поместите это ключевое слово, не будет достаточно регистров, поэтому размещение его в слишком большом количестве переменных может снова привести к тому, что некоторые другие из регистров будут исключены.
Однако это всего лишь подсказка, и компилятору не обязательно ее принимать.
Другие советы
Как ты это рассчитал?На практике, register
обычно ничего не делает.Это хлам из тех времен, когда технология компиляции была чрезвычайно примитивной и компиляторы не могли сами определить распределение регистров.Предполагалось, что это будет подсказка о необходимости выделения регистра для этой переменной и будет полезна для очень часто используемых переменных.Сейчас большинство компиляторов просто игнорируют это и распределяют регистры по своим алгоритмам.
В gcc регистр определенно не игнорируется, если вы не укажете параметры оптимизации.Тестирование вашего кода с помощью чего-то вроде этого
unsigned int array[10];
int n;
#define REG register
int main()
{
REG unsigned int a, b, c;
for (n = 0; n < 10; ++n){
c = a + b;
b = a;
a = c;
array[n] = c;
}
}
вы получаете (в зависимости от того, определен REG или пуст)
http://picasaweb.google.com/lh/photo/v2hBpl6D-soIdBXUOmAeMw?feat=directlink
Слева показан результат использования регистров.
Доступно ограниченное количество регистров, поэтому пометка всего как регистра не приведет к помещению всего в регистры.Бенчмаркинг — единственный способ узнать, поможет это или нет.Хороший компилятор должен уметь самостоятельно определять, какие переменные помещать в регистры, поэтому вам, вероятно, следует провести еще несколько тестов, прежде чем вы решите, что ключевые слова регистра помогают.
Идея использования регистра заключается в том, что ваша переменная используется очень часто.Если с вашей переменной будет произведена какая-либо операция, она все равно будет скопирована в регистр.Таким образом, счетчики (индексные переменные) являются кандидатами на этот модификатор.На примере Диего Торрес Милано от 15 янв. 2010, в 01:57 я бы сделал так:
unsigned int array[10];
int main()
{
register int n;
unsigned int a = 1, b = 2, c;
for (n = 0; n < 10; ++n){
c = a + b;
b = a;
a = c;
array[n] = c;
}
}
Существует ограничение на количество выделяемых регистров.Если вы откажетесь от этого, вы просто получите менее эффективный код.
Я считаю, что если то, что вы делаете, настолько важно, что вам приходится самому решать, что попадает в регистр, а что нет, вам следует писать это на языке ассемблера.
Что касается языков общего назначения, я твердо убежден, что компилятор может лучше решить, что находится в регистре, чем человек.Доказательством тому является то, что, хотя вы не уверены, сколько переменных вы можете поместить в регистры, ваш компилятор знает это наверняка.