Как я могу отключить векторизацию при использовании GCC?

#gcc #vectorization #sse #simd #auto-vectorization

#gcc #векторизация #sse #simd #автоматическая векторизация

Вопрос:

Я компилирую свой код, используя следующую команду:

 gcc -O3 -ftree-vectorizer-verbose=6 -msse4.1 -ffast-math 
  

При этом все оптимизации включены.

Но я хочу отключить векторизацию, сохранив другие оптимизации.

Ответ №1:

Большинство переключателей GCC можно использовать с no префиксом, чтобы отключить их поведение. Попробуйте с -fno-tree-vectorize помощью (после -O3 в командной строке).

Комментарии:

1. Я попробовал это и все же обнаружил в своем коде регистр xmm0 и вызовы __ieee754_exp_avx. @Mat ? любая помощь приветствуется.

2. @Hugo, вы должны различать автоматическую векторизацию и использование инструкций SIMD. Вы можете попробовать -mno-sse -mno-avx и аналогичные варианты, чтобы сообщить компилятору, чтобы он не выдавал какой-либо SIMD-код.

3. @maxschlepzig: обратите внимание, что x86-64 использует регистры XMM как часть соглашения о вызовах для скалярного float / double. При -mno-sse этом вам нужно будет полностью избегать любой математики FP (по крайней мере, при вызове / возврате функции). Для кода ядра или чего-то еще обычно достаточно избегать любой математики FP, чтобы избежать любых инструкций x87 внутри функций, а GCC не выполняет автоматическую векторизацию с помощью инструкций MMX, даже если SSE2 недоступен, поэтому вам обычно не нужно -mno-mmx .

Ответ №2:

вы также можете выборочно включать и отключать векторизацию с помощью атрибутов или прагм функции оптимизации

http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

http://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html

например

 __attribute__((optimize("no-tree-vectorize")))
void f(double * restrict a, double * restrict b)
{
    for (int i = 0; i < 256; i  )
        a[i]  = b[i];
}
  

Ответ №3:

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

 extern "C" __attribute__((optimize("no-tree-vectorize")))
/* Subroutine */
int s111_ (integer * ntimes, integer * ld, integer * n,
           real * ctime, real * dtime,
           real * __restrict a, real * b, real * c__, real * d__,
           real * e, real * aa, real * bb, real * cc)
{
    ....
    for (i__ = 2; i__ <= i__2; i__  = 2)
        a[i__] = a[i__ - 1]   b[i__];
    ....
  

В случае, опубликованном выше, удаление restrict использовалось для выполнения задания, но теперь g 6.0 нельзя остановить от векторизации путем удаления __restrict .