2010-01-15 4 views
9

У меня есть что-то вроде этогоКогда использовать регистры в C?

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, он работает медленнее, чем сейчас, но быстрее, чем если не используются регистры.

Может кто-нибудь объяснить это мне? Благодарю.

+3

Сколько общих регистров имеет целевая архитектура? Кроме того, какой компилятор? –

+0

Я использовал gcc в mac xcode – SuperString

+3

Собираетесь ли вы с включенными полными оптимизациями (например, '-O3')? Большинство оптимизаций компилятора, включая распределение регистров, по умолчанию отключены. Это делает любые тайминги для отладочных сборников (скомпилированных без какого-либо варианта на '-O') совершенно бессмысленным. – Crashworks

ответ

12

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

Это всего лишь намек, и компилятор не должен его принимать.

+1

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

+2

Передача переменной 'register' по адресу просто сообщает компилятору, чтобы он пролистал ее на стек. Это вполне законно в C++ (но не ANSI C). – Crashworks

+0

Обратите внимание, что иногда на чипе недостаточно регистров. Вы просто используете программу 'request', чтобы использовать регистр. Он не может его использовать. –

13

Как вы это сделали? На практике register обычно ничего не делает. Это крутой момент, когда технология компилятора была чрезвычайно примитивной, и компиляторы не могли сами определить распределение регистров. Предполагалось, что это будет намек на то, чтобы выделить регистр этой переменной и был полезен для часто используемых переменных. В настоящее время большинство компиляторов просто игнорируют его и выделяют регистры в соответствии с их собственными алгоритмами.

+2

Я слышал много мест, что этот флаг игнорируется, но я никогда не видел ничего, чтобы поддержать это, кроме слухов. У вас есть источники? По моему опыту с gcc этот флаг иногда может иметь значение (хотя я признаю, что разница обычно отрицательная). – SoapBox

+0

@soap dsimcha прав, это реликвия прошедших времен. wiki it google it и т. д. - вы найдете свое доказательство. –

+0

, но факт в том, что я вычислил время, и я получаю результат, как я сказал в проблеме. – SuperString

1

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

+0

«Бенчмаркинг - это единственный способ узнать, поможет ли это или нет». Ну, он говорит, что он сравнился, и что он придумал результаты для трех разных случаев. Если его контрольные показатели неверны, то повторение его теста снова не сделает их правильными ;-) –

+0

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

-1

Существует ограничение на распределение регистров. Если вы превзошли его, вы просто получите менее эффективный код.

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

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

4

В 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 определен или пуст)

diff http://picasaweb.google.com/lh/photo/v2hBpl6D-soIdBXUOmAeMw?feat=directlink

Слева показан результат использования регистров.

+1

На каком уровне оптимизации он игнорируется? – Potatoswatter

+0

Это зависит от оптимизируемого кода. Проверьте сборщик, сгенерированный в вашем конкретном случае. –

Смежные вопросы