Компиляторная оптимизация, заставляющая производительность замедлиться

У меня есть одна странная проблема. У меня есть следующая часть кода:

template<clss index, class policy>
inline int CBase<index,policy>::func(const A& test_in, int* srcPtr ,int* dstPtr)
{
    int width = test_in.width();
    int height = test_in.height();

    double d = 0.0; //here is the problem
    for(int y = 0; y < height; y++)
    {

        //Pointer initializations

        //multiplication involving y
        //ex: int z = someBigNumber*y + someOtherBigNumber;
        for(int x = 0; x < width; x++)
        {
            //multiplication involving x
        //ex: int z = someBigNumber*x + someOtherBigNumber;
            if(soemCondition)
            {
                // floating point calculations
            }
            *dstPtr++ = array[*srcPtr++];
        }
    }
}

Внутренний цикл выполняется почти 200 000 раз, и целая функция берет 100 мс для завершения. (представленное использование AQTimer)

Я нашел неиспользуемую переменную double d = 0.0; вне внешнего цикла и удаленный то же. После этого изменения внезапно метод берет 500 мс для того же количества выполнения. (В 5 раз медленнее).

Это поведение восстанавливаемо в различных машинах с различными типами процессора. (Core2, dualcore процессоры).

Я использую компилятор VC6 с уровнем оптимизации O2. Follwing являются другими используемыми параметрами компилятора:

 -MD -O2 -Z7 -GR -GX -G5 -X -GF -EHa

Я подозревал оптимизацию компилятора и удалил компиляторную оптимизацию /O2. После того, как та функция стала нормальной, и требуется 100 мс в качестве старого кода.

Кто-либо мог пролить некоторый свет на это странное поведение?

Почему компиляторная оптимизация должна замедлить производительность, когда я удаляю неиспользуемую переменную?

Примечание: Ассемблерный код (перед и после изменения) смотрел то же.

5
задан Georg Fritzsche 29 April 2010 в 07:18
поделиться

3 ответа

Если ассемблерный код выглядит одинаково до и после изменения, ошибка каким-то образом связана с тем, как вы рассчитываете время функции.

5
ответ дан 13 December 2019 в 22:04
поделиться

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

На самом деле, ответ таков: «вы используете компилятор с ошибками. Ожидайте ошибочного поведения, особенно когда включена оптимизация».

Я не думаю, что переходите на современный компилятор (или просто тестируете код на одном из них). ) - это вариант?

Очевидно, что сгенерированная сборка не может быть такой же, иначе не было бы разницы в производительности.

Единственный вопрос - , где разница. А с ошибочным компилятором вполне может быть какая-то совершенно несвязанная часть кода, которая внезапно компилируется по-другому и ломается. Однако, скорее всего, ассемблерный код, сгенерированный для этой функции, не тот же самый, и различия настолько незначительны, что вы их не заметили.

4
ответ дан 13 December 2019 в 22:04
поделиться

Объявить width и height как const {unsigned} int. { Следует использовать беззнаковый , поскольку высота и ширина никогда не являются отрицательными. }

const int width = test_in.width();
const int height = test_in.height();

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

Предлагаю распечатать ассемблерный код версий с неиспользованным double и без него. Это даст вам представление о мыслительном процессе компилятора.

1
ответ дан 13 December 2019 в 22:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: