В чем причина снижения производительности внутреннего цикла после обновления? - PullRequest
0 голосов
/ 29 января 2019

У меня есть алгоритм матрицы, свернутый вручную, который находит наибольшее число правого нижнего квадрата квадратной матрицы (таким образом, при итерации некоторые части «перепрыгивают») - сохраняются в виде плотной матрицы.После обновления с до это выглядит намного медленнее - примерно на 50% в целом.После некоторого исследования это было расположено во внутреннем цикле функции, находящей абсолютное наибольшее значение.Если посмотреть на вывод , то, похоже, это связано с тем, что некоторые дополнительные инструкции вставлены в узкий цикл.Кажется, переработка цикла разными способами решает или частично решает проблему., по-видимому, не имеет этой "проблемы" в сравнении.

Упрощенные примеры (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

Так что мой вопрос: так ли этопросто (известная?) ошибка оптимизатора (?) или есть какая-то логика того, что в данном случае выглядит как очевидный промах оптимизации?

Использование последней стабильной версии 15.9.5

Обновление: Дополнительные s, которые я вижу, перед кодами перехода - самый простой способ найти в проводнике компилятора - щелкнуть правой кнопкой мыши на if и затем "прокрутить до».

...