У меня есть алгоритм матрицы, свернутый вручную, который находит наибольшее число правого нижнего квадрата квадратной матрицы (таким образом, при итерации некоторые части «перепрыгивают») - сохраняются в виде плотной матрицы.После обновления с vs2010 до vs2017 это выглядит намного медленнее - примерно на 50% в целом.После некоторого исследования это было расположено во внутреннем цикле функции, находящей абсолютное наибольшее значение.Если посмотреть на вывод на ассемблере , то, похоже, это связано с тем, что некоторые дополнительные инструкции mov вставлены в узкий цикл.Кажется, переработка цикла разными способами решает или частично решает проблему. gcc , по-видимому, не имеет этой "проблемы" в сравнении.
Упрощенные примеры (fabs
не всегда необходимо воспроизвести):
#include <cmath>
#include <iostream>
int f_slow(double *A, size_t from, size_t w)
{
double biga_absval = *A;
size_t ir = 0,ic=0;
for ( size_t j = 0; j < w; j++ ) {
size_t n = j*w;
for ( ; n < j*w+w; n++ ) {
if ( fabs(A[n]) <= biga_absval ) {
biga_absval = fabs( A[n] );
ir = j;
ic = n;
}
n++;
}
}
std::cout << ir <<ic;
return 0;
}
int f_fast(double *A, size_t from, size_t w)
{
double* biga = A;
double biga_absval = *biga;
double* n_begin = A + from;
double* n_end = A + w;
for (double* A_n = n_begin; A_n < n_end; ++A_n) {
if (fabs(*A_n) > biga_absval) {
biga_absval = fabs(*A_n);
biga = A_n;
}
}
std::cout << biga;
return 0;
}
int f_faster(double *A, size_t from, size_t w)
{
double biga_absval = *A;
size_t ir = 0,ic=0;
for ( size_t j = 0; j < w; j++ ) {
size_t n = j;
for ( ; n < j*w+w; n++ ) {
if ( fabs(A[n]) > biga_absval ) {
biga_absval = fabs( A[n] );
ir = j;
ic = n - j*w;
}
n++;
}
}
std::cout << ir <<ic;
return 0;
}
Обратите внимание : примеры были созданы для просмотра только результатов (и индексы и т. Д. Не обязательно имеют смысл):
https://godbolt.org/z/q9rWwi
Так что мой вопрос: так ли этопросто (известная?) ошибка оптимизатора (?) или есть какая-то логика того, что в данном случае выглядит как очевидный промах оптимизации?
Использование последней стабильной версии vs2017 15.9.5
Обновление: Дополнительные mov s, которые я вижу, перед кодами перехода - самый простой способ найти в проводнике компилятора - щелкнуть правой кнопкой мыши на if
и затем "прокрутить до».