Оптимизация компилятора, вызывающая производительность, чтобы замедлить
-
02-10-2019 - |
Вопрос
У меня одна странная проблема. У меня есть следующий кусок кода:
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 Processors).
Я использую компилятор VC6 с уровнем оптимизации O2
Отказ ФОЛЛВИНГ - это другие параметры компилятора:
-MD -O2 -Z7 -GR -GX -G5 -X -GF -EHa
Я подозревал оптимизацию компилятора и удалил оптимизацию компилятора /O2
. Отказ После этого функция стала нормальной, и она принимает 100 мс в качестве старого кода.
Может ли кто-нибудь бросить свет на это странное поведение?
Почему оптимизация компилятора должна замедлить производительность при удалении неиспользованной переменной?
Примечание. Код сборки (до и после изменения) выглядел так же.
Нет правильного решения
Другие советы
Если код сборки выглядит одинаково до и после изменений, ошибка как-то подключена к тому, как вы время функции.
VC6 глючится как ад. Известно, что генерируют неверный код в нескольких случаях, и его оптимизатор тоже не все, что расширен. Компилятор является более десяти лет, и даже не поддержал много лет.
Так что на самом деле ответ: «Вы используете багги компилятора. Ожидайте багги поведение, особенно когда оптимизация включена».
Я не полагаю, обновление до современного компилятора (или просто тестирование кода на один) - это опция?
Очевидно, что сгенерированная сборка не может быть прежней, или не будет разницы производительности.
Единственный вопрос куда Разница лежит. А с баггиком компилятором вполне может быть некоторая совершенно не связанная часть кода, который внезапно скомпилирован по-разному и разрывается. Скорее всего, код сборки, сгенерированный для этой функции, нет То же самое, и различия настолько тонкие, вы их не заметили.
Объявлять width
а также height
Как const {unsigned} ints. {То беззначный следует использовать поскольку высоты и ширины никогда не являются отрицательными.}
const int width = test_in.width();
const int height = test_in.height();
Это помогает компилятору с оптимизацией. Со значениями как const
, он может разместить их в коде или в регистров, зная, что они не изменится. Кроме того, он снимает компилятор должен догадаться, что переменные меняются или нет.
Я предлагаю распечатывать сборки кода версий с неиспользованным double
и без. Это даст вам представление о мыслительном процессе компилятора.