Оптимизация компилятора, заставляющая программу работать медленнее
У меня есть следующий фрагмент кода, который я написал в C. Его довольно просто, поскольку он просто правильный бит-сдвиги x
для каждого цикла for.
int main() {
int x = 1;
for (int i = 0; i > -2; i++) {
x >> 2;
}
}
Теперь странная вещь, которая происходит, заключается в том, что когда я просто компилирую ее без каких-либо оптимизаций или оптимизации первого уровня (-O
), она работает просто отлично (я синхронизирую исполняемый файл и его 1.4s
с -O
и 5.4s
без каких-либо оптимизаций.
Теперь, когда я добавляю переключатель -O2
или -O3
для компиляции и времени в результате исполняемого файла, он не останавливается (я тестировал до 60s
).
Любые идеи о том, что может быть причиной этого?
Ответы
Ответ 1
Оптимизированный цикл создает бесконечный цикл, который является результатом вас в зависимости от переполнения целых чисел . Поднятое целочисленное переполнение - это поведение undefined в C
и от этого не должно зависеть. Он может не только запутать разработчиков, но также может быть оптимизирован компилятором.
Сборка (без оптимизации): gcc -std=c99 -S -O0 main.c
_main:
LFB2:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
movl $1, -4(%rbp)
movl $0, -8(%rbp)
jmp L2
L3:
incl -8(%rbp)
L2:
cmpl $-2, -8(%rbp)
jg L3
movl $0, %eax
leave
ret
Сборка (оптимизированный уровень 3): gcc -std = c99 -S -O3 main.c
_main:
LFB2:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
L2:
jmp L2 #<- infinite loop
Ответ 2
Вы получите окончательный ответ, посмотрев на созданный двоичный файл (используя objdump
или что-то еще).
Но, как отмечали другие, это, вероятно, потому, что вы полагаетесь на поведение undefined. Одно из возможных объяснений заключается в том, что компилятор может предположить, что i
никогда не будет меньше -2
, и поэтому полностью устранит условие и преобразует его в бесконечный цикл.
Кроме того, ваш код не имеет видимых побочных эффектов, поэтому компилятор также может оптимизировать всю программу до нуля, если ей нравится.
Ответ 3
Дополнительная информация о том, почему целые переполнения undefined можно найти здесь:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
Найдите абзац "Переполнение целых чисел".