Все источники утверждают, что в циклах использование регистровых переменных очень хорошо для производительности. Для меня остаётся не до конца понятен вопрос как компилятор оптимизирует код в том месте, где происходит сравнение индексной переменной i с переменой length.
double array[100ULL];
size_t length = 20ULL;
for(register size_t i = 0ULL; i < length - 1ULL; i++){
array[i] = (double)i;
}
В этом примере индексная переменная i - регистровая. Но сравнение внутри for происходит с переменной length, которая НЕ объявлена как регистровая. Помимо прочего перед сравнением происходит математическая операция.
Хочу для себя прояснить пару-тройку моментов:
Будет ли откомпиллированная программа при каждой итерации цикла
производить эту математическую операцию (вычитание единицы из
меременной length) раз за разом или эта операция будет произведена
только один раз перед началом цикла?
Догадается ли компилятор оптимизировать переменную length в
регстровую?
Какой код будет правильнее с точки зрения производительности и
однозначности для компилятора: тот, что выше, или нижеприведённый?
И есть ли вообще разница для современных компиляторов?
Второй вариант кода, в котором обе сравниваемые переменные регистровые и операция вычитания однозначно производится перед циклом:
double array[100ULL];
register const size_t length = 10ULL - 1ULL;
for(register size_t i = 0ULL; i < length; i++){
array[i] = (double)i;
}
Трансляция кода в asm ситуацию не прояснила, поэтому задаю напрямую.
Ответ
Забудьте об этом слове register, оно давно не имеет никакого смысла.
Ответы на вопросы 1-2 зависят от компилятора; наверное, можно найти старый тупой компилятор, который не сумеет выполнить такие простые оптимизации.. А разумный - вообще может использовать какие-нибудь векторные команды процессора или что еще.
Так что ответ на вопрос 3 - нет, такой простой цикл будет оптимизирован любым более-менее разумным компилятором.
Кстати, VC++2017 просто развернул этот цикл в
mov eax, 1
xor ebx, ebx
cvtsi2sd xmm1, rbx
movsd QWORD PTR array$[rsp], xmm1
xorps xmm1, xmm1
cvtsi2sd xmm1, rax
mov eax, 2
cvtsi2sd xmm2, rax
mov eax, 3
.....
movsd QWORD PTR array$[rsp+128], xmm2
movsd QWORD PTR array$[rsp+136], xmm1
xorps xmm1, xmm1
cvtsi2sd xmm1, rax
movsd QWORD PTR array$[rsp+144], xmm1
ругнувшись при этом на слово register как давно не поддерживаемое... Результат видите сами.
Очень старенький OpenWatcom пошел по циклическому пути -
L$1:
cmp eax,13H
jae L$2
mov dword ptr 320H[esp],eax
xor ecx,ecx
add edx,8
mov dword ptr 324H[esp],ecx
inc eax
fild qword ptr 320H[esp]
fstp qword ptr -8[esp+edx]
jmp L$1
но, как видите, вычислив 19 сразу, и работая только с регистрами...
Комментариев нет:
Отправить комментарий