Цикл с нулевым временем выполнения

Возможно ли иметь цикл с нулевым временем выполнения? Я думаю, что даже пустой цикл должен иметь время выполнения, так как с ним связаны издержки.

74

Решение

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

Примеры

Например, следующий код:

int main()
{
int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
++j ;
}
}

составлено с gcc 4.9 с использованием -O3 флаг в основном сводится к следующему (увидеть это в прямом эфире):

main:
xorl  %eax, %eax  #
ret

Практически все оптимизации позволили попасть под как будто правило, единственное исключение, о котором я знаю, это копия Элисон что позволяет влиять на наблюдаемое поведение.

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

#include <stdio.h>

int main()
{
int j = 0 ;
if( false ) // The loop will never execute
{
for( int i = 0; i < 10000; ++i )
{
printf( "%d\n", j ) ;
++j ;
}
}
}

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

int j = 0 ;
for( int i = 0; i < 10000; ++i )
{
++j ;
}
printf( "%d\n", j ) ;

можно оптимизировать до (увидеть это в прямом эфире):

movl    $10000, %esi    #,
movl    $.LC0, %edi #,
xorl    %eax, %eax  #
call    printf  #

Мы видим, что в этом нет петли.

Где как-будто правило, охватываемое стандартом

как будто правило рассматривается в проекте стандарта C99 5.1.2.3 Выполнение программы который говорит:

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

как будто правило также относится к C ++, gcc выдаст тот же результат и в режиме C ++. Проект стандарта C ++ охватывает это в разделе 1.9 Выполнение программы:

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

121

Другие решения

Да — если компилятор определяет, что цикл является мертвым кодом (никогда не будет выполняться), он не будет генерировать для него код. Этот цикл будет иметь 0 времени выполнения, хотя, строго говоря, он не существует на уровне машинного кода.

52

Помимо оптимизации компилятора, некоторые архитектуры ЦП, в частности DSP, имеют цикл с нулевыми накладными расходами, посредством чего цикл с фиксированным числом итераций эффективно оптимизируется аппаратными средствами, см., например, http://www.dsprelated.com/showmessage/20681/1.php

12

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

Харбисон и Стил, C: Справочное руководство

3
По вопросам рекламы [email protected]